Package org.apache.cocoon.components.source

Source Code of org.apache.cocoon.components.source.SitemapSource

/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved.        *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included  with this distribution in *
* the LICENSE file.                                                         *
*****************************************************************************/

package org.apache.cocoon.components.source;

import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.ComponentSelector;
import org.apache.cocoon.Constants;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.Processor;
import org.apache.cocoon.caching.PipelineCacheKey;
import org.apache.cocoon.components.pipeline.CacheableEventPipeline;
import org.apache.cocoon.components.pipeline.EventPipeline;
import org.apache.cocoon.components.pipeline.StreamPipeline;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.ModifiableSource;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Source;
import org.apache.cocoon.environment.wrapper.EnvironmentWrapper;
import org.apache.cocoon.serialization.Serializer;
import org.apache.cocoon.util.HashUtil;
import org.apache.cocoon.xml.AbstractXMLConsumer;
import org.apache.cocoon.xml.ContentHandlerWrapper;
import org.apache.cocoon.xml.XMLConsumer;
import org.apache.cocoon.xml.XMLProducer;
import org.apache.log.Logger;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

/**
* Description of a source which is defined by a pipeline.
*
* @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
* @version CVS $Revision: 1.2 $ $Date: 2002/01/15 11:10:52 $
*/

public final class SitemapSource
extends AbstractXMLConsumer
implements ModifiableSource {

    /** The last modification date or 0 */
    private long lastModificationDate;

    /** The system id */
    private String systemId;

    /** The uri */
    private String uri;

    /** The current ComponentManager */
    private ComponentManager manager;

    /** The processor */
    private Processor processor;

    /** The environment */
    private EnvironmentWrapper environment;

    /** The prefix for the processing */
    private String prefix;

    /** The <code>EventPipeline</code> */
    private EventPipeline eventPipeline;

    /** The <code>StreamPipeline</code> */
    private StreamPipeline pipeline;

    /** The redirect <code>Source</code> */
    private Source redirectSource;

    /** The <code>SAXException</code> if unable to get resource */
    private ProcessingException exception;

    /** Do I need a refresh ? */
    private boolean needsRefresh;

    /**
     * Construct a new object
     */
    public SitemapSource(Environment      env,
                         ComponentManager manager,
                         Processor        sitemap,
                         String           uri,
                         Logger           logger)
    throws IOException, ProcessingException {

        this.manager = manager;
        this.setLogger(logger);
        // remove the protocol
        int protocolEnd = uri.indexOf(':');
        if (protocolEnd != -1) {
            uri = uri.substring(protocolEnd + 1);
        }

        // does the uri point to this sitemap or to the root sitemap?
        if (uri.startsWith("//")) {
            uri = uri.substring(2);
            Processor processor = null;
            try {
                processor = (Processor)this.manager.lookup(Processor.ROLE);
            } catch (ComponentException e) {
                throw new ProcessingException("Cannot get Processor instance", e);
            }
            this.prefix = ""; // start at the root
            this.processor = processor;
        } else if (uri.startsWith("/")) {
            this.prefix = null;
            uri = uri.substring(1);
            this.processor = sitemap;
        }

        // build the request uri which is relative to the context
        // create the queryString (if available)
        String requestURI = (this.prefix == null ? env.getURIPrefix() + uri : uri);
        String queryString = null;
        int queryStringPos = requestURI.indexOf('?');
        if (queryStringPos != -1) {
            queryString = requestURI.substring(queryStringPos+1);
            requestURI = requestURI.substring(0, queryStringPos);
        }
        Request request= (Request)env.getObjectModel().get(Constants.REQUEST_OBJECT);
        boolean isDefaultPort = "http".equalsIgnoreCase(request.getScheme()) && 80 == request.getServerPort();
        StringBuffer sysID = new StringBuffer(request.getScheme()).append("://")
                        .append(request.getServerName());
       
        if ( ! isDefaultPort ) {
            sysID.append(':').append(request.getServerPort());
        }
        sysID.append(request.getContextPath()).append('/').append(requestURI);
        queryStringPos = uri.indexOf('?');
        if (queryStringPos != -1) {
            uri = uri.substring(0, queryStringPos);
            sysID.append('?').append(queryString);
        }
        this.systemId = sysID.toString();
        this.environment = new EnvironmentWrapper(env, requestURI, queryString, logger);
        this.uri = uri;
        this.refresh();
    }

    /**
     * Get the last modification date of the source or 0 if it
     * is not possible to determine the date.
     */
    public long getLastModified() {
        if (this.needsRefresh) {
            this.refresh();
        }
        return this.lastModificationDate;
    }

    /**
     * Get the content length of the source or -1 if it
     * is not possible to determine the length.
     */
    public long getContentLength() {
        return -1;
    }

    /**
     * Return an <code>InputStream</code> object to read from the source.
     */
    public InputStream getInputStream()
    throws ProcessingException, IOException {
        if (this.needsRefresh) {
            this.refresh();
        }
        // VG: Why exception is not thrown in constructor?
        if (this.exception != null) {
            throw this.exception;
        }
        ComponentSelector serializerSelector = null;
        Serializer serializer = null;
        try {

            serializerSelector = (ComponentSelector) this.manager.lookup(Serializer.ROLE + "Selector");
            serializer = (Serializer)serializerSelector.select("xml");
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            serializer.setOutputStream(os);

            this.toSAX(serializer);

            return new ByteArrayInputStream(os.toByteArray());
        } catch (ComponentException cme) {
            throw new ProcessingException("could not lookup pipeline components", cme);
        } catch (ProcessingException e) {
            throw e;
        } catch (Exception e) {
            throw new ProcessingException("Exception during processing of " + this.systemId, e);
        } finally {
            if (serializer != null) serializerSelector.release(serializer);
            if (serializerSelector != null) this.manager.release(serializerSelector);
            reset();
        }
    }

    /**
     * Return the unique identifer for this source
     */
    public String getSystemId() {
        return this.systemId;
    }

    /**
     * Refresh this object and update the last modified date
     * and content length.
     */
    public void refresh() {
        reset();
        try {
            // initialize the pipelines
            this.eventPipeline = (EventPipeline)this.manager.lookup(EventPipeline.ROLE);
            this.pipeline = (StreamPipeline)this.manager.lookup(StreamPipeline.ROLE);

            this.pipeline.setEventPipeline(eventPipeline);
            // set dummy consumer
            ((XMLProducer)eventPipeline).setConsumer(this);

            this.environment.setURI(this.prefix, this.uri);
            this.processor.process(this.environment, pipeline, eventPipeline);
            this.environment.changeToLastContext();
                String redirectURL = this.environment.getRedirectURL();
                if (redirectURL == null) {
                    if (this.eventPipeline instanceof CacheableEventPipeline) {
                        CacheableEventPipeline cep = (CacheableEventPipeline)this.eventPipeline;
                        PipelineCacheKey pck = cep.generateKey(this.environment);
                        Map validity = null;
                        if (pck != null) {
                            validity = cep.generateValidity(this.environment);
                            if (validity != null) {
                                // the event pipeline is cacheable
                                // now calculate a last modification date
                                String hashKey = pck.toString() + validity.toString();
                                this.lastModificationDate = HashUtil.hash(hashKey);
                            }
                        }
                    }
                } else {
                    if (redirectURL.indexOf(":") == -1) {
                        redirectURL = "cocoon:/" + redirectURL;
                    }
                    this.redirectSource = this.environment.resolve(redirectURL);
                    this.lastModificationDate = this.redirectSource.getLastModified();
                }
        } catch (ProcessingException e) {
            reset();
            this.exception = e;
        } catch (Exception e) {
            reset();
            this.exception = new ProcessingException("Could not get sitemap source "
                                                     + this.systemId, e);
        }
        this.needsRefresh = false;
    }

    /**
     * Return a new <code>InputSource</code> object
     */
    public InputSource getInputSource()
    throws ProcessingException, IOException {
        InputSource newObject = new InputSource(this.getInputStream());
        newObject.setSystemId(this.systemId);
        return newObject;
    }

    /**
     * Stream content to the content handler
     */
    public void toSAX(ContentHandler contentHandler)
        throws SAXException, ProcessingException
    {
        if (this.needsRefresh) {
            this.refresh();
        }
        if (this.exception != null) {
            throw this.exception;
        }
        try {
            XMLConsumer consumer;
            if (contentHandler instanceof XMLConsumer) {
                consumer = (XMLConsumer)contentHandler;
            } else if (contentHandler instanceof LexicalHandler) {
                consumer = new ContentHandlerWrapper(contentHandler, (LexicalHandler)contentHandler);
            } else {
                consumer = new ContentHandlerWrapper(contentHandler);
            }
            if (this.redirectSource != null) {
                this.redirectSource.toSAX(consumer);
            } else {
                ((XMLProducer)eventPipeline).setConsumer(consumer);
                eventPipeline.process(this.environment);
            }
        } catch (ComponentException cme) {
            throw new ProcessingException("Could not lookup pipeline components", cme);
        } catch (ProcessingException e) {
            // Preserve original exception
            throw e;
        } catch (Exception e) {
            throw new ProcessingException("Exception during processing of "
                                          + this.systemId, e);
        } finally {
            reset();
        }
    }

    private void reset() {
        if (this.eventPipeline != null) this.manager.release(this.eventPipeline);
        if (this.pipeline != null) this.manager.release(this.pipeline);
        this.eventPipeline = null;
        this.pipeline = null;
        this.lastModificationDate = 0;
        this.environment.reset();
        if (this.redirectSource != null) this.redirectSource.recycle();
        this.redirectSource = null;
        this.exception = null;
        this.needsRefresh = true;
    }

    public void recycle() {
        reset();
    }
}
TOP

Related Classes of org.apache.cocoon.components.source.SitemapSource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.