in core/cocoon-pipeline/cocoon-pipeline-impl/src/main/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java [763:924]
protected boolean processReader(Environment environment) throws ProcessingException {
try {
boolean usedCache = false;
OutputStream outputStream = null;
SourceValidity readerValidity = null;
PipelineCacheKey pcKey = null;
// test if reader is cacheable
Serializable readerKey = null;
if (super.reader instanceof CacheableProcessingComponent) {
readerKey = ((CacheableProcessingComponent)super.reader).getKey();
}
boolean finished = false;
if (readerKey != null) {
// response is cacheable, build the key
pcKey = new PipelineCacheKey();
pcKey.addKey(new ComponentCacheKey(ComponentCacheKey.ComponentType_Reader,
this.readerRole,
readerKey));
while (!finished) {
finished = true;
// now we have the key to get the cached object
CachedResponse cachedObject = this.cache.get(pcKey);
if (cachedObject != null) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Found cached response for '" +
environment.getURI() + "' using key: " + pcKey);
}
SourceValidity[] validities = cachedObject.getValidityObjects();
if (validities == null || validities.length != 1) {
// to avoid getting here again and again, we delete it
this.cache.remove(pcKey);
if (getLogger().isDebugEnabled()) {
getLogger().debug("Cached response for '" + environment.getURI() +
"' using key: " + pcKey + " is invalid.");
}
this.cachedResponse = null;
} else {
SourceValidity cachedValidity = validities[0];
int valid = cachedValidity.isValid();
if (valid == SourceValidity.UNKNOWN) {
// get reader validity and compare
readerValidity = ((CacheableProcessingComponent) super.reader).getValidity();
if (readerValidity != null) {
valid = cachedValidity.isValid(readerValidity);
if (valid == SourceValidity.UNKNOWN) {
readerValidity = null;
}
}
}
if (valid == SourceValidity.VALID) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("processReader: using valid cached content for '" +
environment.getURI() + "'.");
}
byte[] response = cachedObject.getResponse();
if (response.length > 0) {
usedCache = true;
if (cachedObject.getContentType() != null) {
environment.setContentType(cachedObject.getContentType());
} else {
setMimeTypeForReader(environment);
}
outputStream = environment.getOutputStream(0);
environment.setContentLength(response.length);
outputStream.write(response);
}
} else {
if (getLogger().isDebugEnabled()) {
getLogger().debug("processReader: cached content is invalid for '" +
environment.getURI() + "'.");
}
// remove invalid cached object
this.cache.remove(pcKey);
}
}
} else {
// check if something is being generated right now
if (!waitForLock(pcKey)) {
finished = false;
continue;
}
}
}
}
if (!usedCache) {
// make sure lock will be released
try {
if (pcKey != null) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("processReader: caching content for further requests of '" +
environment.getURI() + "'.");
}
generateLock(pcKey);
if (readerValidity == null) {
readerValidity = ((CacheableProcessingComponent)super.reader).getValidity();
}
if (readerValidity != null) {
outputStream = environment.getOutputStream(this.outputBufferSize);
outputStream = new CachingOutputStream(outputStream);
}
}
setMimeTypeForReader(environment);
if (this.reader.shouldSetContentLength()) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
this.reader.setOutputStream(os);
this.reader.generate();
} catch (SourceException se) {
//it's valid that generate() method returns SourceException (which extension to IOException)
//and pipeline execution should be more clever
throw SourceUtil.handle(se);
}
environment.setContentLength(os.size());
if (outputStream == null) {
outputStream = environment.getOutputStream(0);
}
os.writeTo(outputStream);
} else {
if (outputStream == null) {
outputStream = environment.getOutputStream(this.outputBufferSize);
}
try {
this.reader.setOutputStream(outputStream);
this.reader.generate();
} catch (SourceException se) {
//it's valid that generate() method returns SourceException (which extension to IOException)
//and pipeline execution should be more clever
throw SourceUtil.handle(se);
}
}
// store the response
if (pcKey != null && readerValidity != null) {
final CachedResponse res = new CachedResponse(new SourceValidity[] {readerValidity},
((CachingOutputStream)outputStream).getContent());
res.setContentType(environment.getContentType());
this.cache.store(pcKey, res);
}
} finally {
releaseLock(pcKey);
}
}
} catch (Exception e) {
handleException(e);
}
//Request has been succesfully processed, set approporiate status code
environment.setStatus(HttpServletResponse.SC_OK);
return true;
}