View Javadoc

1   /*
2    * $Id: AbstractBufferOperationContentModel.java,v 1.5 2010/08/10 14:02:30 oeuillot Exp $
3    */
4   package org.rcfaces.core.internal.content;
5   
6   import java.io.ByteArrayInputStream;
7   import java.io.IOException;
8   import java.io.InputStream;
9   
10  import javax.faces.context.ExternalContext;
11  import javax.faces.context.FacesContext;
12  import javax.servlet.ServletContext;
13  import javax.servlet.http.HttpServletRequest;
14  import javax.servlet.http.HttpServletResponse;
15  
16  import org.apache.commons.logging.Log;
17  import org.apache.commons.logging.LogFactory;
18  import org.rcfaces.core.internal.RcfacesContext;
19  import org.rcfaces.core.internal.contentStorage.GZipedResolvedContent;
20  import org.rcfaces.core.internal.contentStorage.IResolvedContent;
21  import org.rcfaces.core.internal.lang.ByteBufferOutputStream;
22  import org.rcfaces.core.internal.resource.IResourceLoaderFactory;
23  import org.rcfaces.core.internal.resource.IResourceLoaderFactory.IResourceLoader;
24  
25  /**
26   * 
27   * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
28   * @version $Revision: 1.5 $ $Date: 2010/08/10 14:02:30 $
29   */
30  public abstract class AbstractBufferOperationContentModel extends
31          AbstractOperationContentModel implements IOperationContentLoader {
32  
33      private static final String REVISION = "$Revision: 1.5 $";
34  
35      private static final long serialVersionUID = -7085466442454979874L;
36  
37      private static final Log LOG = LogFactory
38              .getLog(AbstractBufferOperationContentModel.class);
39  
40      private static final int INITIAL_BUFFER_SIZE = 8 * 1024;
41  
42      public AbstractBufferOperationContentModel(String resourceURL,
43              String versionId, String operationId,
44              String filterParametersToParse, IBufferOperation styleOperation,
45              String specifiedResourceKey) {
46          super(resourceURL, versionId, operationId, filterParametersToParse,
47                  styleOperation, specifiedResourceKey);
48      }
49  
50      protected IResourceLoaderFactory getResourceLoaderFactory(
51              FacesContext facesContext) {
52  
53          RcfacesContext rcfacesContext = RcfacesContext
54                  .getInstance(facesContext);
55  
56          IResourceLoaderFactory resourceLoaderFactory;
57          if (rcfacesContext.isDesignerMode()) {
58              resourceLoaderFactory = Constants.getDesignerImageLoaderFactory();
59  
60          } else {
61              resourceLoaderFactory = Constants.getImageLoaderFactory();
62          }
63  
64          return resourceLoaderFactory;
65      }
66  
67      protected IResolvedContent getResolvedContent() {
68          return new GZipedResolvedContent(this);
69      }
70  
71      protected abstract String getCharsetFromStream(InputStream inputStream);
72  
73      protected abstract String getDefaultMimeType();
74  
75      protected abstract boolean isMimeTypeValid(String downloadedContentType);
76  
77      /**
78       * 
79       * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
80       * @version $Revision: 1.5 $ $Date: 2010/08/10 14:02:30 $
81       */
82      public static class ContentInformation {
83          private String charSet;
84  
85          private long lastModified;
86  
87          private long length;
88  
89          public final String getCharSet() {
90              return charSet;
91          }
92  
93          public final long getLastModified() {
94              return lastModified;
95          }
96  
97          public final long getLength() {
98              return length;
99          }
100 
101         public void merge(ContentInformation newContentInformation) {
102             if (newContentInformation.lastModified > lastModified) {
103                 lastModified = newContentInformation.lastModified;
104             }
105 
106             length += newContentInformation.getLength();
107         }
108     }
109 
110     public String loadContent(FacesContext facesContext,
111             IResourceLoaderFactory resourceLoaderFactory, String path,
112             String defaultCharset, ContentInformation contentInfoRef[]) {
113 
114         if (facesContext == null) {
115             facesContext = FacesContext.getCurrentInstance();
116         }
117 
118         ExternalContext externalContext = facesContext.getExternalContext();
119 
120         HttpServletRequest request = (HttpServletRequest) externalContext
121                 .getRequest();
122         HttpServletResponse response = (HttpServletResponse) externalContext
123                 .getResponse();
124         ServletContext context = (ServletContext) externalContext.getContext();
125 
126         IResourceLoader resourceLoader = resourceLoaderFactory.loadResource(
127                 context, request, response, path);
128 
129         String downloadedContentType = resourceLoader.getContentType();
130 
131         if (downloadedContentType != null) {
132             int idx = downloadedContentType.indexOf(';');
133             if (idx > 0) {
134                 downloadedContentType = downloadedContentType.substring(0, idx);
135             }
136         }
137 
138         if (downloadedContentType == null
139                 || isMimeTypeValid(downloadedContentType) == false) {
140             LOG.error("Different content types requested='"
141                     + getDefaultMimeType() + "' loaded='"
142                     + downloadedContentType + "' for path '" + path + "'.");
143 
144             return null;
145         }
146 
147         InputStream inputStream = resourceLoader.openStream();
148 
149         if (inputStream == null) {
150             LOG.error("Can not get resource specified by path '" + path + "'.");
151 
152             return null;
153         }
154 
155         ContentInformation contentInfo = new ContentInformation();
156 
157         if (contentInfoRef != null) {
158             contentInfoRef[0] = contentInfo;
159         }
160 
161         try {
162             int size = INITIAL_BUFFER_SIZE;
163             long originalSize = resourceLoader.getContentLength();
164             contentInfo.length = originalSize;
165 
166             if (originalSize > 0 && originalSize < INITIAL_BUFFER_SIZE) {
167                 size = (int) originalSize + 256;
168             }
169 
170             ByteBufferOutputStream bous = new ByteBufferOutputStream(size);
171 
172             byte b[] = new byte[size];
173             for (;;) {
174                 int ret = inputStream.read(b);
175                 if (ret <= 0) {
176                     break;
177                 }
178 
179                 bous.write(b, 0, ret);
180             }
181 
182             bous.close();
183 
184             byte buffer[] = bous.toByteArray();
185 
186             String charSet = getCharsetFromStream(new ByteArrayInputStream(
187                     buffer));
188 
189             if (charSet == null) {
190                 charSet = defaultCharset;
191             }
192 
193             contentInfo.charSet = charSet;
194             contentInfo.lastModified = resourceLoader.getLastModified();
195 
196             return new String(buffer, charSet);
197 
198         } catch (IOException ex) {
199             LOG.error("Can not make buffer", ex);
200             return null;
201 
202         } finally {
203             try {
204                 inputStream.close();
205 
206             } catch (IOException ex) {
207                 LOG.debug("Can not close resource '" + path + "'.", ex);
208             }
209         }
210     }
211 
212 }