Package org.apache.cocoon.components.source

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

/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.logger.Logger;

import org.apache.excalibur.source.SourceException;

import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.Processor;
import org.apache.cocoon.components.CocoonComponentManager;
import org.apache.cocoon.components.pipeline.ProcessingPipeline;
import org.apache.cocoon.components.sax.XMLDeserializer;
import org.apache.cocoon.components.sax.XMLSerializer;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.ModifiableSource;
import org.apache.cocoon.environment.wrapper.EnvironmentWrapper;
import org.apache.cocoon.xml.AbstractXMLConsumer;
import org.apache.cocoon.xml.ContentHandlerWrapper;
import org.apache.cocoon.xml.XMLConsumer;
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.net.MalformedURLException;

/**
* Description of a source which is defined by a pipeline.
*
* @deprecated by the Avalon Excalibur Source Resolving
* @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
* @version CVS $Id: SitemapSource.java 149504 2005-02-02 09:40:13Z sylvain $
*/
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 pipeline processor */
    private Processor pipelineProcessor;

    /** The environment */
    private EnvironmentWrapper environment;

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

    /** The <code>ProcessingPipeline</code> */
    private ProcessingPipeline processingPipeline;

    /** The redirect <code>Source</code> */
    private org.apache.excalibur.source.Source redirectSource;

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

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

    /** The unique key for this processing */
    private Object processKey;

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

        Environment env = CocoonComponentManager.getCurrentEnvironment();
        if ( env == null ) {
            throw new MalformedURLException("The cocoon protocol can not be used outside an environment.");
        }

        this.manager = manager;
        this.enableLogging(logger);
        boolean rawMode = false;

        // remove the protocol
        int position = uri.indexOf(':') + 1;
        if (position != 0) {
            // check for subprotocol
            if (uri.startsWith("raw:", position)) {
                position += 4;
                rawMode = true;
            }
        }

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

        // create the queryString (if available)
        String queryString = null;
        int queryStringPos = uri.indexOf('?', position);
        if (queryStringPos != -1) {
            queryString = uri.substring(queryStringPos + 1);
            uri = uri.substring(position, queryStringPos);
        } else if (position > 0) {
            uri = uri.substring(position);
        }

        // build the request uri which is relative to the context
        String requestURI = (this.prefix == null ? env.getURIPrefix() + uri : uri);

        // create system ID
        this.systemId = queryString == null ?
            "cocoon://" + requestURI :
            "cocoon://" + requestURI + "?" + queryString;

        this.environment = new EnvironmentWrapper(env, requestURI, queryString, logger, manager, rawMode);
        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 new ProcessingException(this.exception);
        }

        if (this.redirectSource != null) {
            try {
                return this.redirectSource.getInputStream();
            } catch (SourceException se) {
                throw SourceUtil.handle(se);
            }
        }

        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            this.environment.setOutputStream(os);
            CocoonComponentManager.enterEnvironment(this.environment,
                                                    this.manager,
                                                    this.pipelineProcessor);
            try {
                this.processingPipeline.process(this.environment);
            } finally {
                CocoonComponentManager.leaveEnvironment();
            }
            return new ByteArrayInputStream(os.toByteArray());

        } catch (ProcessingException e) {
            throw e;
        } catch (Exception e) {
            throw new ProcessingException("Exception during processing of " + this.systemId, e);
        } finally {
            // Unhide wrapped environment output stream
            this.environment.setOutputStream(null);
            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 {
            this.processKey = CocoonComponentManager.startProcessing(this.environment);
            this.environment.setURI(this.prefix, this.uri);
            this.processingPipeline = this.processor.buildPipeline(this.environment);
            this.pipelineProcessor = CocoonComponentManager.getActiveProcessor(this.environment);
            String redirectURL = this.environment.getRedirectURL();
            if (redirectURL != null) {
                if (redirectURL.indexOf(":") == -1) {
                    redirectURL = "cocoon:/" + redirectURL;
                }
                this.redirectSource = this.environment.resolveURI(redirectURL);
                this.lastModificationDate = this.redirectSource.getLastModified();
            }
        } catch (SAXException e) {
            reset();
            this.exception = e;
        } catch (Exception e) {
            reset();
            this.exception = new SAXException("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
    {
        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) {
                SourceUtil.parse(this.manager, this.redirectSource, consumer);
            } else {
                // We have to buffer the result in order to get
                // clean environment stack handling.
                XMLSerializer xmls = (XMLSerializer) this.manager.lookup(XMLSerializer.ROLE);
                Object fragment;
                CocoonComponentManager.enterEnvironment(this.environment,
                                                        this.manager,
                                                        this.pipelineProcessor);
                try {
                    this.processingPipeline.process(this.environment, xmls);
                    fragment = xmls.getSAXFragment();
                } finally {
                    this.manager.release(xmls);
                    CocoonComponentManager.leaveEnvironment();
                }
                XMLDeserializer xmld = (XMLDeserializer) this.manager.lookup(XMLDeserializer.ROLE);
                try {
                    xmld.setConsumer(consumer);
                    xmld.deserialize(fragment);
                } finally {
                    this.manager.release(xmld);
                }
            }
        } catch (SAXException e) {
            // Preserve original exception
            throw e;
        } catch (Exception e) {
            throw new SAXException("Exception during processing of "
                                          + this.systemId, e);
        } finally {
            reset();
        }
    }

    private void reset() {
        if (this.processingPipeline != null) this.processingPipeline.release();
        if (this.processKey != null) {
            CocoonComponentManager.endProcessing(this.environment, this.processKey);
            this.processKey = null;
        }
        this.processingPipeline = null;
        this.lastModificationDate = 0;
        this.environment.release(this.redirectSource);
        this.environment.reset();
        this.redirectSource = null;
        this.exception = null;
        this.needsRefresh = true;
        this.pipelineProcessor = null;
    }

    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.