protected boolean processReader()

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