View Javadoc

1   package org.rcfaces.core.internal.content;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.io.Serializable;
6   import java.net.FileNameMap;
7   import java.net.URLConnection;
8   import java.util.Collections;
9   import java.util.HashMap;
10  import java.util.Map;
11  import java.util.StringTokenizer;
12  
13  import javax.faces.context.ExternalContext;
14  import javax.faces.context.FacesContext;
15  import javax.servlet.ServletContext;
16  import javax.servlet.http.HttpServletRequest;
17  import javax.servlet.http.HttpServletResponse;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.rcfaces.core.internal.contentAccessor.IGeneratedResourceInformation;
22  import org.rcfaces.core.internal.contentAccessor.IGenerationResourceInformation;
23  import org.rcfaces.core.internal.contentAccessor.IResourceKeyParticipant;
24  import org.rcfaces.core.internal.contentStorage.IResolvedContent;
25  import org.rcfaces.core.internal.lang.StringAppender;
26  import org.rcfaces.core.internal.resource.IResourceLoaderFactory;
27  import org.rcfaces.core.internal.resource.IResourceLoaderFactory.IResourceLoader;
28  import org.rcfaces.core.internal.version.HashCodeTools;
29  import org.rcfaces.core.lang.IAdaptable;
30  import org.rcfaces.core.model.BasicContentModel;
31  
32  /**
33   * 
34   * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
35   * @version $Revision: 1.11 $ $Date: 2010/08/10 14:02:30 $
36   */
37  public abstract class AbstractOperationContentModel extends BasicContentModel
38          implements Serializable, IResolvedContent, IAdaptable {
39      private static final String REVISION = "$Revision: 1.11 $";
40  
41      private static final long serialVersionUID = 4218209439999498360L;
42  
43      private static final Log LOG = LogFactory
44              .getLog(AbstractOperationContentModel.class);
45  
46      private static final int RESOURCE_KEY_INITIAL_SIZE = 4096;
47  
48      private static final FileNameMap fileNameMap = URLConnection
49              .getFileNameMap();
50  
51      /**
52       * 
53       */
54      protected static final IFileBuffer INVALID_BUFFERED_FILE = new IFileBuffer() {
55          private static final String REVISION = "$Revision: 1.11 $";
56  
57          public int getSize() {
58              return 0;
59          }
60  
61          public String getName() {
62              return "*** Invalid buffer ***";
63          }
64  
65          public InputStream getContent() {
66              return null;
67          }
68  
69          public String getContentType() {
70              return null;
71          }
72  
73          public long getModificationDate() {
74              return 0;
75          }
76  
77          public String getHash() {
78              return null;
79          }
80  
81          public String getETag() {
82              return null;
83          }
84  
85          public boolean isInitialized() {
86              return true;
87          }
88  
89          public void setErrored() {
90          }
91  
92          public boolean isErrored() {
93              return true;
94          }
95  
96          public String getRedirection() {
97              return null;
98          }
99  
100         public void initializeRedirection(String url) {
101         }
102 
103     };
104 
105     private final String resourceURL;
106 
107     private final String operationId;
108 
109     private String filterParametersToParse;
110 
111     private String resourceKey;
112 
113     private transient Map filterParameters;
114 
115     private transient IBufferOperation bufferOperation;
116 
117     private boolean versioned;
118 
119     private transient IFileBuffer fileBuffer;
120 
121     private boolean sourceInfoRecorded = false;
122 
123     private long sourceLastModified;
124 
125     private long sourceLength;
126 
127     private final String versionId;
128 
129     private final String specifiedResourceKey;
130 
131     public AbstractOperationContentModel(String resourceURL, String versionId,
132             String operationId, String filterParametersToParse,
133             IBufferOperation bufferOperation, String specifiedResourceKey) {
134         this.resourceURL = resourceURL;
135         this.operationId = operationId;
136         this.filterParametersToParse = filterParametersToParse;
137         this.bufferOperation = bufferOperation;
138         this.versionId = versionId;
139         this.specifiedResourceKey = specifiedResourceKey;
140 
141         setWrappedData(this);
142     }
143 
144     public void setInformations(
145             IGenerationResourceInformation generationInformation,
146             IGeneratedResourceInformation generatedInformation) {
147         super.setInformations(generationInformation, generatedInformation);
148 
149         String contentType = generatedInformation.getResponseMimeType();
150         if (contentType == null) {
151             contentType = generatedInformation.getSourceMimeType();
152         }
153 
154         String suffix = generatedInformation.getResponseSuffix();
155 
156         if (suffix == null && contentType != null) {
157             suffix = ContentAdapterFactory.getSuffixByMimeType(contentType);
158 
159             generatedInformation.setResponseSuffix(suffix);
160         }
161     }
162 
163     public final synchronized Map getFilterParameters() {
164         if (filterParameters != null) {
165             return filterParameters;
166         }
167 
168         if (filterParametersToParse == null
169                 || filterParametersToParse.length() < 1) {
170             filterParameters = Collections.EMPTY_MAP;
171             return filterParameters;
172         }
173 
174         StringTokenizer st = new StringTokenizer(filterParametersToParse, ",");
175 
176         filterParameters = new HashMap(st.countTokens());
177         int idx = 0;
178         for (; st.hasMoreTokens();) {
179             String token = st.nextToken().trim();
180 
181             String pName;
182             String pValue;
183 
184             int idxEq = token.indexOf('=');
185             if (idxEq >= 0) {
186                 pName = token.substring(0, idxEq).trim();
187                 pValue = token.substring(idxEq + 1).trim();
188 
189             } else {
190                 pName = "#" + idx;
191                 pValue = token.trim();
192 
193                 idx++;
194             }
195 
196             filterParameters.put(pName, pValue);
197         }
198 
199         return filterParameters;
200     }
201 
202     public Object getAdapter(Class adapter, Object parameter) {
203         if (IResolvedContent.class.equals(adapter)) {
204             return getResolvedContent();
205         }
206 
207         return null;
208     }
209 
210     protected IResolvedContent getResolvedContent() {
211         return this;
212     }
213 
214     public boolean isProcessAtRequest() {
215         return false;
216     }
217 
218     public boolean isErrored() {
219         return getFileBuffer().isErrored();
220     }
221 
222     private synchronized IFileBuffer getFileBuffer() {
223         if (fileBuffer != null) {
224             return fileBuffer;
225         }
226 
227         fileBuffer = createFileBuffer();
228 
229         generatedInformation.setResponseMimeType(fileBuffer.getContentType());
230 
231         return fileBuffer;
232     }
233 
234     public InputStream getInputStream() throws IOException {
235         return getFileBuffer().getContent();
236     }
237 
238     public IBufferOperation getBufferOperation(FacesContext facesContext) {
239         if (bufferOperation != null) {
240             return bufferOperation;
241         }
242 
243         bufferOperation = createBufferOperation(facesContext);
244 
245         return bufferOperation;
246     }
247 
248     protected abstract IBufferOperation createBufferOperation(
249             FacesContext facesContext);
250 
251     protected abstract IFileBuffer createFileBuffer();
252 
253     protected final String getResourceURL() {
254         return resourceURL;
255     }
256 
257     protected final String getOperationId() {
258         return operationId;
259     }
260 
261     public long getModificationDate() {
262         return getFileBuffer().getModificationDate();
263     }
264 
265     public int getLength() {
266         return getFileBuffer().getSize();
267     }
268 
269     public String getETag() {
270         return getFileBuffer().getETag();
271     }
272 
273     public String getHash() {
274         return getFileBuffer().getHash();
275     }
276 
277     public String getResourceKey() {
278         synchronized (this) {
279             if (resourceKey == null) {
280                 StringAppender sa = new StringAppender(operationId,
281                         RESOURCE_KEY_INITIAL_SIZE);
282 
283                 if (filterParametersToParse != null) {
284                     sa.append(IResourceKeyParticipant.RESOURCE_KEY_SEPARATOR);
285                     sa.append(filterParametersToParse);
286                 }
287 
288                 sa.append(IResourceKeyParticipant.RESOURCE_KEY_SEPARATOR);
289 
290                 sa.append(resourceURL);
291 
292                 if (versionId != null) {
293                     sa.append(IResourceKeyParticipant.RESOURCE_KEY_SEPARATOR);
294                     sa.append(versionId);
295                 }
296 
297                 if (generationInformation instanceof IResourceKeyParticipant) {
298                     ((IResourceKeyParticipant) generationInformation)
299                             .participeKey(sa);
300                 }
301 
302                 if (generatedInformation instanceof IResourceKeyParticipant) {
303                     ((IResourceKeyParticipant) generatedInformation)
304                             .participeKey(sa);
305                 }
306 
307                 resourceKey = sa.toString();
308             }
309 
310         }
311         return resourceKey;
312     }
313 
314     public boolean isVersioned() {
315         return versioned;
316     }
317 
318     public void setVersioned(boolean versioned) {
319         this.versioned = versioned;
320     }
321 
322     public void appendHashInformations(StringAppender sa) {
323         String url = getResourceURL();
324         if (url != null) {
325             loadSourceInfos(null);
326         }
327 
328         StringAppender sa2 = new StringAppender(512);
329 
330         if (url != null) {
331             sa2.append(url);
332         }
333 
334         if (sourceLastModified > 0) {
335             sa2.append(IResourceKeyParticipant.RESOURCE_KEY_SEPARATOR);
336             sa2.append(sourceLastModified);
337         }
338 
339         if (sourceLength > 0) {
340             sa2.append(IResourceKeyParticipant.RESOURCE_KEY_SEPARATOR);
341             sa2.append(sourceLength);
342         }
343 
344         String key = sa2.toString();
345 
346         String result = HashCodeTools.computeURLFormat(null, key, key, -1);
347 
348         sa.append(result);
349     }
350 
351     private synchronized void loadSourceInfos(FacesContext facesContext) {
352         if (sourceInfoRecorded) {
353             return;
354         }
355         sourceInfoRecorded = true;
356 
357         if (facesContext == null) {
358             facesContext = FacesContext.getCurrentInstance();
359         }
360 
361         IResourceLoaderFactory resourceLoaderFactory = getResourceLoaderFactory(facesContext);
362 
363         ExternalContext externalContext = facesContext.getExternalContext();
364 
365         HttpServletRequest request = (HttpServletRequest) externalContext
366                 .getRequest();
367         HttpServletResponse response = (HttpServletResponse) externalContext
368                 .getResponse();
369         ServletContext context = (ServletContext) externalContext.getContext();
370 
371         IResourceLoader resourceLoader = resourceLoaderFactory.loadResource(
372                 context, request, response, getResourceURL());
373 
374         sourceLastModified = resourceLoader.getLastModified();
375         sourceLength = resourceLoader.getContentLength();
376     }
377 
378     protected abstract IResourceLoaderFactory getResourceLoaderFactory(
379             FacesContext facesContext);
380 
381     public int hashCode() {
382         final int prime = 31;
383         int result = 1;
384         result = prime
385                 * result
386                 + ((filterParametersToParse == null) ? 0
387                         : filterParametersToParse.hashCode());
388         result = prime * result
389                 + ((operationId == null) ? 0 : operationId.hashCode());
390         result = prime * result
391                 + ((resourceURL == null) ? 0 : resourceURL.hashCode());
392         return result;
393     }
394 
395     public boolean equals(Object obj) {
396         if (this == obj)
397             return true;
398         if (obj == null)
399             return false;
400         if (getClass() != obj.getClass())
401             return false;
402         final AbstractOperationContentModel other = (AbstractOperationContentModel) obj;
403         if (filterParametersToParse == null) {
404             if (other.filterParametersToParse != null)
405                 return false;
406         } else if (!filterParametersToParse
407                 .equals(other.filterParametersToParse))
408             return false;
409         if (operationId == null) {
410             if (other.operationId != null)
411                 return false;
412         } else if (!operationId.equals(other.operationId))
413             return false;
414         if (resourceURL == null) {
415             if (other.resourceURL != null)
416                 return false;
417         } else if (!resourceURL.equals(other.resourceURL))
418             return false;
419         return true;
420     }
421 
422     public String getContentType() {
423         return generatedInformation.getResponseMimeType();
424     }
425 
426     public String getURLSuffix() {
427         return generatedInformation.getResponseSuffix();
428     }
429 
430 }