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
35
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 }