KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > pipeline > impl > CachingPointProcessingPipeline


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.pipeline.impl;
17
18 import org.apache.avalon.framework.component.ComponentException;
19 import org.apache.avalon.framework.parameters.ParameterException;
20 import org.apache.avalon.framework.parameters.Parameters;
21 import org.apache.cocoon.ProcessingException;
22 import org.apache.cocoon.caching.CachedResponse;
23 import org.apache.cocoon.caching.CachingOutputStream;
24 import org.apache.cocoon.caching.ComponentCacheKey;
25 import org.apache.cocoon.components.sax.XMLDeserializer;
26 import org.apache.cocoon.components.sax.XMLSerializer;
27 import org.apache.cocoon.components.sax.XMLTeePipe;
28 import org.apache.cocoon.environment.Environment;
29 import org.apache.cocoon.xml.XMLConsumer;
30 import org.apache.cocoon.xml.XMLProducer;
31 import org.apache.commons.lang.BooleanUtils;
32 import org.apache.excalibur.source.SourceValidity;
33
34 import java.io.OutputStream JavaDoc;
35 import java.io.Serializable JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.ListIterator JavaDoc;
39
40 /**
41  * The CachingPointProcessingPipeline
42  *
43  * @since 2.1
44  * @author <a HREF="mailto:Michael.Melhem@managesoft.com">Michael Melhem</a>
45  * @version CVS $Id: CachingPointProcessingPipeline.java 123779 2004-12-31 10:18:38Z antonio $
46  */

47 public class CachingPointProcessingPipeline
48     extends AbstractCachingProcessingPipeline {
49
50     protected ArrayList JavaDoc isCachePoint = new ArrayList JavaDoc();
51     protected ArrayList JavaDoc xmlSerializerArray = new ArrayList JavaDoc();
52     protected boolean nextIsCachePoint = false;
53     protected String JavaDoc autoCachingPointSwitch;
54     protected boolean autoCachingPoint = true;
55
56    /**
57     * The <code>CachingPointProcessingPipeline</code> is configurable.
58     * The autoCachingPoint algorithm can be switced on/off
59     * in the sitemap.xmap
60     */

61     public void parameterize(Parameters config) throws ParameterException {
62         super.parameterize(config);
63         this.autoCachingPointSwitch = config.getParameter("autoCachingPoint", null);
64
65         if (this.getLogger().isDebugEnabled()) {
66             getLogger().debug("Auto caching-point is set to = '" + this.autoCachingPointSwitch + "'");
67         }
68
69         // Default is that auto caching-point is on
70
if (this.autoCachingPointSwitch == null) {
71             this.autoCachingPoint=true;
72         } else {
73             this.autoCachingPoint = BooleanUtils.toBoolean(this.autoCachingPointSwitch);
74         }
75     }
76
77     /**
78      * Set the generator.
79      */

80     public void setGenerator (String JavaDoc role, String JavaDoc source, Parameters param, Parameters hintParam)
81     throws ProcessingException {
82         super.setGenerator(role, source, param, hintParam);
83
84         // check the hint param for a "caching-point" hint
85
String JavaDoc pipelinehint = null;
86         try {
87             pipelinehint = hintParam.getParameter("caching-point", null);
88
89             if (this.getLogger().isDebugEnabled()) {
90                 getLogger().debug("generator caching-point pipeline-hint is set to: " + pipelinehint);
91             }
92         } catch (Exception JavaDoc ex) {
93             if (this.getLogger().isWarnEnabled()) {
94                 getLogger().warn("caching-point hint Exception, pipeline-hint ignored: " + ex);
95             }
96         }
97
98         // if this generator is manually set to "caching-point" (via pipeline-hint)
99
// then ensure the next component is caching.
100
this.nextIsCachePoint = BooleanUtils.toBoolean(pipelinehint);
101     }
102
103     /**
104      * Add a transformer.
105      */

106     public void addTransformer (String JavaDoc role, String JavaDoc source, Parameters param, Parameters hintParam)
107     throws ProcessingException {
108         super.addTransformer(role, source, param, hintParam);
109
110         // check the hint param for a "caching-point" hint
111
String JavaDoc pipelinehint = null;
112         try {
113             pipelinehint = hintParam.getParameter("caching-point", null);
114
115             if (this.getLogger().isDebugEnabled()) {
116                 getLogger().debug("transformer caching-point pipeline-hint is set to: " + pipelinehint);
117             }
118         } catch (Exception JavaDoc ex) {
119             if (this.getLogger().isWarnEnabled()) {
120                 getLogger().warn("caching-point hint Exception, pipeline-hint ignored: " + ex);
121             }
122         }
123
124         // add caching point flag
125
// default value is false
126
this.isCachePoint.add(BooleanUtils.toBooleanObject(this.nextIsCachePoint));
127
128         // if this transformer is manually set to "caching-point" (via pipeline-hint)
129
// then ensure the next component is caching.
130
this.nextIsCachePoint = BooleanUtils.toBoolean(pipelinehint);
131     }
132
133     /**
134      * Determine if the given branch-point
135      * is a caching-point
136      *
137      * Please Note: this method is used by auto caching-point
138      * and is of no consequence when auto caching-point is switched off
139      */

140     public void informBranchPoint() {
141         if (this.autoCachingPoint && this.generator != null) {
142             this.nextIsCachePoint = true;
143             if (this.getLogger().isDebugEnabled()) {
144                 this.getLogger().debug("Informed Pipeline of branch point");
145             }
146         }
147     }
148
149     /**
150      * Cache longest cacheable path plus cache points.
151      */

152     protected void cacheResults(Environment environment, OutputStream os) throws Exception JavaDoc {
153
154         if (this.toCacheKey != null) {
155             if (this.cacheCompleteResponse) {
156                 if (this.getLogger().isDebugEnabled()) {
157                     this.getLogger().debug("Cached: caching complete response; pSisze"
158                                            + this.toCacheKey.size() + " Key " + this.toCacheKey);
159                 }
160                 CachedResponse response = new CachedResponse(this.toCacheSourceValidities,
161                                           ((CachingOutputStream)os).getContent());
162                 response.setContentType(environment.getContentType());
163                 this.cache.store(this.toCacheKey.copy(), response);
164                 //
165
// Scan back along the pipelineCacheKey for
166
// for any cachepoint(s)
167
//
168
this.toCacheKey.removeUntilCachePoint();
169
170                 //
171
// adjust the validities object
172
// to reflect the new length of the pipeline cache key.
173
//
174
// REVISIT: Is it enough to simply reduce the length of the validities array?
175
//
176
if (this.toCacheKey.size() > 0) {
177                     SourceValidity[] copy = new SourceValidity[this.toCacheKey.size()];
178                     System.arraycopy(this.toCacheSourceValidities, 0, copy, 0, copy.length);
179                     this.toCacheSourceValidities = copy;
180                 }
181             }
182
183             if (this.toCacheKey.size() > 0) {
184                 ListIterator JavaDoc itt = this.xmlSerializerArray.listIterator(this.xmlSerializerArray.size());
185                 while (itt.hasPrevious()) {
186                     XMLSerializer serializer = (XMLSerializer) itt.previous();
187                     CachedResponse response = new CachedResponse(this.toCacheSourceValidities,
188                                               (byte[])serializer.getSAXFragment());
189                     this.cache.store(this.toCacheKey.copy(), response);
190
191                     if (this.getLogger().isDebugEnabled()) {
192                         this.getLogger().debug("Caching results for the following key: "
193                             + this.toCacheKey);
194                     }
195
196                     //
197
// Check for further cachepoints
198
//
199
toCacheKey.removeUntilCachePoint();
200                     if (this.toCacheKey.size()==0)
201                         // no cachePoint found in key
202
break;
203
204                     //
205
// re-calculate validities array
206
//
207
SourceValidity[] copy = new SourceValidity[this.toCacheKey.size()];
208                     System.arraycopy(this.toCacheSourceValidities, 0, copy, 0, copy.length);
209                     this.toCacheSourceValidities = copy;
210                 } //end serializer loop
211
}
212         }
213     }
214
215     /**
216      * Create a new ComponentCachekey
217      * ComponentCacheKeys can be flagged as cachepoints
218      */

219     protected ComponentCacheKey newComponentCacheKey(int type, String JavaDoc role,Serializable JavaDoc key) {
220         boolean cachePoint = false;
221
222         if (type == ComponentCacheKey.ComponentType_Transformer) {
223             cachePoint =
224                 ((Boolean JavaDoc)this.isCachePoint.get(this.firstNotCacheableTransformerIndex)).booleanValue();
225         } else if (type == ComponentCacheKey.ComponentType_Serializer) {
226             cachePoint = this.nextIsCachePoint;
227         }
228         return new ComponentCacheKey(type, role, key, cachePoint);
229     }
230
231     /**
232      * Connect the caching point pipeline.
233      */

234     protected void connectCachingPipeline(Environment environment)
235     throws ProcessingException {
236             try {
237                 XMLSerializer localXMLSerializer = null;
238                 XMLSerializer cachePointXMLSerializer = null;
239                 if (!this.cacheCompleteResponse) {
240                     this.xmlSerializer = (XMLSerializer)this.manager.lookup( XMLSerializer.ROLE );
241                     localXMLSerializer = this.xmlSerializer;
242                 }
243
244                 if (this.cachedResponse == null) {
245                     XMLProducer prev = super.generator;
246                     XMLConsumer next;
247
248                     int cacheableTransformerCount = this.firstNotCacheableTransformerIndex;
249                     int currentTransformerIndex = 0; //start with the first transformer
250

251                     Iterator JavaDoc itt = this.transformers.iterator();
252                     while (itt.hasNext()) {
253                         next = (XMLConsumer) itt.next();
254
255                         // if we have cacheable transformers,
256
// check the tranformers for cachepoints
257
if (cacheableTransformerCount > 0) {
258                             if ((this.isCachePoint.get(currentTransformerIndex) != null) &&
259                                     ((Boolean JavaDoc)this.isCachePoint.get(currentTransformerIndex)).booleanValue()) {
260
261                                 cachePointXMLSerializer = ((XMLSerializer)
262                                 this.manager.lookup( XMLSerializer.ROLE ));
263                                 next = new XMLTeePipe(next, cachePointXMLSerializer);
264                                 this.xmlSerializerArray.add(cachePointXMLSerializer);
265                             }
266                         }
267
268                         // Serializer is not cacheable,
269
// but we have the longest cacheable key. Do default longest key caching
270
if (localXMLSerializer != null) {
271                             if (cacheableTransformerCount == 0) {
272                                 next = new XMLTeePipe(next, localXMLSerializer);
273                                 this.xmlSerializerArray.add(localXMLSerializer);
274                                 localXMLSerializer = null;
275                             } else {
276                                 cacheableTransformerCount--;
277                             }
278                         }
279                         this.connect(environment, prev, next);
280                         prev = (XMLProducer) next;
281
282                         currentTransformerIndex++;
283                     }
284                     next = super.lastConsumer;
285
286                     // if the serializer is not cacheable, but all the transformers are:
287
// (this is default longest key caching)
288
if (localXMLSerializer != null) {
289                         next = new XMLTeePipe(next, localXMLSerializer);
290                         this.xmlSerializerArray.add(localXMLSerializer);
291                         localXMLSerializer = null;
292                     }
293
294                     // else if the serializer is cacheable and has cocoon views
295
else if ((currentTransformerIndex == this.firstNotCacheableTransformerIndex) &&
296                             this.nextIsCachePoint) {
297                         cachePointXMLSerializer = ((XMLSerializer)this.manager.lookup( XMLSerializer.ROLE ));
298                         next = new XMLTeePipe(next, cachePointXMLSerializer);
299                         this.xmlSerializerArray.add(cachePointXMLSerializer);
300                     }
301                     this.connect(environment, prev, next);
302                 } else {
303                     // Here the first part of the pipeline has been retrived from cache
304
// we now check if any part of the rest of the pipeline can be cached
305
this.xmlDeserializer = (XMLDeserializer)this.manager.lookup(XMLDeserializer.ROLE);
306                     // connect the pipeline:
307
XMLProducer prev = xmlDeserializer;
308                     XMLConsumer next;
309                     int cacheableTransformerCount = 0;
310                     Iterator JavaDoc itt = this.transformers.iterator();
311                     while (itt.hasNext()) {
312                         next = (XMLConsumer) itt.next();
313
314                         if (cacheableTransformerCount >= this.firstProcessedTransformerIndex) {
315
316                             // if we have cacheable transformers left,
317
// then check the tranformers for cachepoints
318
if (cacheableTransformerCount < this.firstNotCacheableTransformerIndex) {
319                                 if (!(prev instanceof XMLDeserializer) &&
320                                         (this.isCachePoint.get(cacheableTransformerCount) != null) &&
321                                         ((Boolean JavaDoc)this.isCachePoint.get(cacheableTransformerCount)).booleanValue()) {
322                                     cachePointXMLSerializer = ((XMLSerializer)this.manager.lookup( XMLSerializer.ROLE ));
323                                     next = new XMLTeePipe(next, cachePointXMLSerializer);
324                                     this.xmlSerializerArray.add(cachePointXMLSerializer);
325                                 }
326                             }
327
328                             // Serializer is not cacheable,
329
// but we have the longest cacheable key. Do default longest key caching
330
if (localXMLSerializer != null && !(prev instanceof XMLDeserializer)
331                                     && cacheableTransformerCount == this.firstNotCacheableTransformerIndex) {
332                                 next = new XMLTeePipe(next, localXMLSerializer);
333                                 this.xmlSerializerArray.add(localXMLSerializer);
334                                 localXMLSerializer = null;
335                             }
336                             this.connect(environment, prev, next);
337                             prev = (XMLProducer)next;
338                         }
339                         cacheableTransformerCount++;
340                     }
341                     next = super.lastConsumer;
342
343                     //*all* the transformers are cacheable, but the serializer is not!! this is longest key
344
if (localXMLSerializer != null && !(prev instanceof XMLDeserializer)) {
345                         next = new XMLTeePipe(next, localXMLSerializer);
346                         this.xmlSerializerArray.add(localXMLSerializer);
347                         localXMLSerializer = null;
348             }
349             // else the serializer is cacheable but has views
350
else if (this.nextIsCachePoint && !(prev instanceof XMLDeserializer) &&
351                             cacheableTransformerCount == this.firstNotCacheableTransformerIndex) {
352                         cachePointXMLSerializer = ((XMLSerializer)this.manager.lookup( XMLSerializer.ROLE ));
353                         next = new XMLTeePipe(next, cachePointXMLSerializer);
354                         this.xmlSerializerArray.add(cachePointXMLSerializer);
355                     }
356                     this.connect(environment, prev, next);
357                 }
358
359             } catch (ComponentException e) {
360                 throw new ProcessingException("Could not connect pipeline.", e);
361             }
362     }
363
364     /**
365      * Recyclable Interface
366      */

367     public void recycle() {
368         super.recycle();
369
370         Iterator JavaDoc itt = this.xmlSerializerArray.iterator();
371         while (itt.hasNext()) {
372             this.manager.release((XMLSerializer) itt.next());
373         }
374         this.isCachePoint.clear();
375         this.xmlSerializerArray.clear();
376         this.nextIsCachePoint = false;
377         this.autoCachingPointSwitch=null;
378     }
379 }
380
Popular Tags