1 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 22 import org.apache.cocoon.ProcessingException; 23 import org.apache.cocoon.caching.CachedResponse; 24 import org.apache.cocoon.caching.CachingOutputStream; 25 import org.apache.cocoon.caching.IdentifierCacheKey; 26 import org.apache.cocoon.components.sax.XMLDeserializer; 27 import org.apache.cocoon.components.sax.XMLSerializer; 28 import org.apache.cocoon.components.sax.XMLTeePipe; 29 import org.apache.cocoon.environment.Environment; 30 import org.apache.cocoon.environment.ObjectModelHelper; 31 import org.apache.cocoon.environment.Response; 32 import org.apache.cocoon.xml.XMLConsumer; 33 34 import org.apache.excalibur.source.SourceValidity; 35 import org.apache.excalibur.source.impl.validity.ExpiresValidity; 36 37 import java.io.ByteArrayOutputStream ; 38 import java.io.OutputStream ; 39 import java.util.Map ; 40 41 53 public class ExpiresCachingProcessingPipeline 54 extends BaseCachingProcessingPipeline { 55 56 57 public static final String CACHE_KEY_KEY = ExpiresCachingProcessingPipeline.class.getName() + "/CacheKey"; 58 59 60 public static final String CACHE_EXPIRES_KEY = ExpiresCachingProcessingPipeline.class.getName() + "/Expires"; 61 62 63 protected SourceValidity cacheValidity; 64 65 66 protected IdentifierCacheKey cacheKey; 67 68 69 protected long cacheExpires; 70 71 72 protected long defaultCacheExpires = 3600; 74 75 protected CachedResponse cachedResponse; 76 77 public void parameterize(Parameters params) 78 throws ParameterException { 79 super.parameterize(params); 80 81 this.defaultCacheExpires = params.getParameterAsLong("cache-expires", this.defaultCacheExpires); 82 } 83 84 87 protected boolean processXMLPipeline(Environment environment) 88 throws ProcessingException { 89 try { 90 if (this.cachedResponse != null) { 91 byte[] content = cachedResponse.getResponse(); 92 93 if ( this.serializer == this.lastConsumer ) { 94 if ( cachedResponse.getContentType() != null ) { 95 environment.setContentType(cachedResponse.getContentType()); 96 } else { 97 this.setMimeTypeForSerializer(environment); 98 } 99 final OutputStream outputStream = environment.getOutputStream(0); 100 if (content.length > 0) { 101 environment.setContentLength(content.length); 102 outputStream.write(content); 103 } 104 } else { 105 this.setMimeTypeForSerializer(environment); 106 this.xmlDeserializer.setConsumer( this.lastConsumer ); 107 this.xmlDeserializer.deserialize( content ); 108 } 109 110 } else { 111 112 114 if ( this.cacheExpires == 0 ) { 115 return super.processXMLPipeline( environment ); 116 } 117 118 this.setMimeTypeForSerializer(environment); 119 byte[] cachedData; 120 if ( this.serializer == this.lastConsumer ) { 121 122 if (this.serializer.shouldSetContentLength()) { 123 OutputStream os = environment.getOutputStream(this.outputBufferSize); 124 125 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 127 this.serializer.setOutputStream(baos); 128 129 this.generator.generate(); 130 131 cachedData = baos.toByteArray(); 132 environment.setContentLength(cachedData.length); 133 os.write(cachedData); 134 } else { 135 CachingOutputStream os = new CachingOutputStream( environment.getOutputStream(this.outputBufferSize) ); 136 this.serializer.setOutputStream( os ); 138 this.generator.generate(); 139 140 cachedData = os.getContent(); 141 } 142 143 } else { 144 this.generator.generate(); 145 cachedData = (byte[])this.xmlSerializer.getSAXFragment(); 146 } 147 148 if (this.cacheValidity != null) { 153 cachedResponse = new CachedResponse(this.cacheValidity, 154 cachedData); 155 cachedResponse.setContentType(environment.getContentType()); 156 this.cache.store(this.cacheKey, cachedResponse); 157 } 158 } 159 } catch (Exception e) { 160 handleException(e); 161 } 162 163 return true; 164 } 165 166 169 protected void connectPipeline(Environment environment) 170 throws ProcessingException { 171 if ( this.lastConsumer != this.serializer ) { 172 if ( this.cachedResponse == null) { 174 if ( this.cacheExpires > 0) { 176 try { 177 final XMLConsumer old = this.lastConsumer; 178 this.xmlSerializer = (XMLSerializer)this.manager.lookup( XMLSerializer.ROLE ); 179 this.lastConsumer = new XMLTeePipe(this.lastConsumer, this.xmlSerializer); 180 181 super.connectPipeline( environment ); 182 183 this.lastConsumer = old; 184 } catch ( ComponentException e ) { 185 throw new ProcessingException("Could not connect pipeline.", e); 186 } 187 } else { 188 super.connectPipeline( environment ); 189 } 190 } else { 191 try { 193 this.xmlDeserializer = (XMLDeserializer)this.manager.lookup(XMLDeserializer.ROLE); 194 } catch ( ComponentException e ) { 195 throw new ProcessingException("Could not connect pipeline.", e); 196 } 197 } 198 } else { 199 if ( this.cachedResponse == null) { 201 super.connectPipeline( environment ); 202 } 203 } 204 } 205 206 209 protected void preparePipeline(Environment environment) 210 throws ProcessingException { 211 final Map objectModel = environment.getObjectModel(); 216 String key = (String )objectModel.get(CACHE_KEY_KEY); 217 if ( key == null ) { 218 key = this.parameters.getParameter("cache-key", null); 219 if ( key == null ) { 220 key = environment.getURIPrefix()+environment.getURI(); 221 } 222 } else { 223 objectModel.remove(CACHE_KEY_KEY); 224 } 225 String expiresValue = (String )objectModel.get(CACHE_EXPIRES_KEY); 226 if ( expiresValue == null ) { 227 this.cacheExpires = this.parameters.getParameterAsLong("cache-expires", this.defaultCacheExpires); 228 } else { 229 this.cacheExpires = Long.valueOf(expiresValue).longValue(); 230 objectModel.remove(CACHE_EXPIRES_KEY); 231 } 232 233 super.preparePipeline( environment ); 235 236 this.cacheKey = new IdentifierCacheKey(key, 238 this.serializer == this.lastConsumer); 239 if ( this.cacheExpires > 0) { 240 this.cacheValidity = new ExpiresValidity(this.cacheExpires*1000); 241 } 242 final boolean purge = this.parameters.getParameterAsBoolean("purge-cache", false); 243 244 this.cachedResponse = this.cache.get(this.cacheKey); 245 if ( this.cachedResponse != null ) { 246 final SourceValidity sv = cachedResponse.getValidityObjects()[0]; 247 if ( purge 248 || (this.cacheExpires != -1 && sv.isValid() != SourceValidity.VALID) ) { 249 this.cache.remove( this.cacheKey ); 250 this.cachedResponse = null; 251 } 252 } 253 if ( this.cacheExpires > 0 254 && (this.reader != null || this.lastConsumer == this.serializer )) { 255 Response res = ObjectModelHelper.getResponse(environment.getObjectModel()); 256 res.setDateHeader("Expires", System.currentTimeMillis() + (this.cacheExpires*1000)); 257 res.setHeader("Cache-Control", "max-age=" + this.cacheExpires + ", public"); 258 } 259 } 260 261 267 public SourceValidity getValidityForEventPipeline() { 268 return this.cacheValidity; 269 } 270 271 274 public String getKeyForEventPipeline() { 275 if (this.cacheKey != null && this.cacheValidity != null) { 276 return this.cacheKey.toString(); 277 } 278 return null; 279 } 280 281 284 public void recycle() { 285 this.cacheKey = null; 286 this.cacheExpires = 0; 287 this.cachedResponse = null; 288 super.recycle(); 289 } 290 291 294 protected boolean processReader(Environment environment) 295 throws ProcessingException { 296 try { 297 if (this.cachedResponse != null) { 298 if ( cachedResponse.getContentType() != null ) { 299 environment.setContentType(cachedResponse.getContentType()); 300 } else { 301 this.setMimeTypeForReader(environment); 302 } 303 304 final byte[] content = cachedResponse.getResponse(); 305 environment.setContentLength(content.length); 306 307 final OutputStream os = environment.getOutputStream(0); 308 os.write(content); 309 310 } else { 311 313 if ( this.cacheExpires == 0 ) { 314 return super.processReader( environment ); 315 } 316 317 byte[] cachedData; 318 319 this.setMimeTypeForReader(environment); 320 if (this.reader.shouldSetContentLength()) { 321 final OutputStream os = environment.getOutputStream(this.outputBufferSize); 322 323 final ByteArrayOutputStream baos = new ByteArrayOutputStream (); 325 this.reader.setOutputStream(baos); 326 327 this.reader.generate(); 328 329 cachedData = baos.toByteArray(); 330 environment.setContentLength(cachedData.length); 331 os.write(cachedData); 332 } else { 333 final CachingOutputStream os = new CachingOutputStream( environment.getOutputStream(this.outputBufferSize) ); 334 this.reader.setOutputStream( os ); 336 this.reader.generate(); 337 338 cachedData = os.getContent(); 339 } 340 341 if (this.cacheValidity != null) { 346 cachedResponse = new CachedResponse(this.cacheValidity, 347 cachedData); 348 cachedResponse.setContentType(environment.getContentType()); 349 this.cache.store(this.cacheKey, cachedResponse); 350 } 351 } 352 } catch (Exception e) { 353 handleException(e); 354 } 355 356 return true; 357 } 358 } 359 | Popular Tags |