org.apache.cocoon.Cocoon.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.cocoon.Cocoon.java

Source

/*
 * 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;

import org.apache.avalon.excalibur.component.ComponentProxyGenerator;
import org.apache.avalon.excalibur.component.DefaultRoleManager;
import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
import org.apache.avalon.excalibur.logger.LoggerManager;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.thread.ThreadSafe;

import org.apache.cocoon.components.CocoonComponentManager;
import org.apache.cocoon.components.ComponentContext;
import org.apache.cocoon.components.PropertyAwareSAXConfigurationHandler;
import org.apache.cocoon.components.pipeline.ProcessingPipeline;
import org.apache.cocoon.components.source.SourceUtil;
import org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.util.ClassUtils;
import org.apache.cocoon.util.Deprecation;
import org.apache.cocoon.util.SimpleSourceResolver;
import org.apache.cocoon.util.Settings;
import org.apache.cocoon.util.PropertySettings;
import org.apache.cocoon.util.SettingsHelper;
import org.apache.cocoon.util.location.Location;
import org.apache.cocoon.util.location.LocationImpl;
import org.apache.cocoon.util.location.LocationUtils;

import org.apache.commons.lang.SystemUtils;
import org.apache.excalibur.instrument.InstrumentManageable;
import org.apache.excalibur.instrument.InstrumentManager;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.source.impl.URLSource;
import org.apache.excalibur.xml.impl.XercesParser;
import org.apache.excalibur.xml.sax.SAXParser;
import org.xml.sax.InputSource;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;

/**
 * The Cocoon Object is the main Kernel for the entire Cocoon system.
 *
 * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a> (Apache Software Foundation)
 * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
 * @author <a href="mailto:leo.sutic@inspireinfrastructure.com">Leo Sutic</a>
 * @version CVS $Id: Cocoon.java 389028 2006-03-27 06:21:40Z rgoers $
 */
public class Cocoon extends AbstractLogEnabled implements ThreadSafe, Component, Initializable, Disposable,
        Modifiable, Processor, Contextualizable, Composable, InstrumentManageable {

    // Register the location finder for Avalon configuration objects and exceptions
    // and keep a strong reference to it.
    private static final LocationUtils.LocationFinder confLocFinder = new LocationUtils.LocationFinder() {
        public Location getLocation(Object obj, String description) {
            if (obj instanceof Configuration) {
                Configuration config = (Configuration) obj;
                String locString = config.getLocation();
                Location result = LocationUtils.parse(locString);
                if (LocationUtils.isKnown(result)) {
                    // Add description
                    StringBuffer desc = new StringBuffer().append('<');
                    // Unfortunately Configuration.getPrefix() is not public
                    try {
                        if (config.getNamespace().startsWith("http://apache.org/cocoon/sitemap/")) {
                            desc.append("map:");
                        }
                    } catch (ConfigurationException e) {
                        // no namespace: ignore
                    }
                    desc.append(config.getName()).append('>');
                    return new LocationImpl(desc.toString(), result);
                } else {
                    return result;
                }
            }

            if (obj instanceof Exception) {
                // Many exceptions in Cocoon have a message like "blah blah at file://foo/bar.xml:12:1"
                String msg = ((Exception) obj).getMessage();
                if (msg == null)
                    return null;

                int pos = msg.lastIndexOf(" at ");
                if (pos != -1) {
                    return LocationUtils.parse(msg.substring(pos + 4));
                } else {
                    // Will try other finders
                    return null;
                }
            }

            // Try next finders.
            return null;
        }
    };

    static {
        LocationUtils.addFinder(confLocFinder);
    }

    static Cocoon instance;

    /** The root Cocoon logger */
    private Logger rootLogger;

    /** The application context */
    private Context context;

    /** The configuration file */
    private Source configurationFile;

    /** The configuration tree */
    private Configuration configuration;

    /** The logger manager */
    private LoggerManager loggerManager;

    /** The instrument manager */
    private InstrumentManager instrumentManager;

    /** The classpath (null if not available) */
    private String classpath;

    /** The working directory (null if not available) */
    private File workDir;

    /** The component manager. */
    private ExcaliburComponentManager componentManager;

    /** The parent component manager. */
    private ComponentManager parentComponentManager;

    /** Flag for disposed or not */
    private boolean disposed;

    /** Active request count */
    private volatile int activeRequestCount;

    /** The Processor if it is ThreadSafe */
    private Processor threadSafeProcessor;

    /** The source resolver */
    protected SourceResolver sourceResolver;

    /** An optional Avalon Component that is called before and after processing all requests. */
    protected RequestListener requestListener;

    /**
     * Creates a new <code>Cocoon</code> instance.
     *
     * @exception ConfigurationException if an error occurs
     */
    public Cocoon() throws ConfigurationException {
        // Set the system properties needed by Xalan2.
        setSystemProperties();

        // HACK: Provide a way to share an instance of Cocoon object between
        //       several servlets/portlets.
        Cocoon.instance = this;
    }

    public void enableLogging(Logger logger) {
        this.rootLogger = logger;
        super.enableLogging(logger.getChildLogger("cocoon"));
    }

    /**
     * Get the parent component manager. For purposes of
     * avoiding extra method calls, the manager parameter may be null.
     *
     * @param manager the parent component manager. May be <code>null</code>
     */
    public void compose(ComponentManager manager) throws ComponentException {
        this.parentComponentManager = manager;
    }

    /**
     * Describe <code>contextualize</code> method here.
     *
     * @param context a <code>Context</code> value
     * @exception ContextException if an error occurs
     */
    public void contextualize(Context context) throws ContextException {
        if (this.context == null) {
            this.context = new ComponentContext(context);
            SettingsHelper.createSettings((DefaultContext) this.context, getLogger());
            ((DefaultContext) this.context).makeReadOnly();

            this.classpath = (String) context.get(Constants.CONTEXT_CLASSPATH);
            this.workDir = (File) context.get(Constants.CONTEXT_WORK_DIR);
            try {
                // FIXME: add a configuration option for the refresh delay.
                // for now, hard-coded to 1 second.
                URLSource urlSource = new URLSource();
                urlSource.init((URL) context.get(Constants.CONTEXT_CONFIG_URL), null);
                this.configurationFile = new DelayedRefreshSourceWrapper(urlSource, 1000L);

            } catch (IOException e) {
                throw new ContextException("Could not open configuration file.", e);
            } catch (Exception e) {
                throw new ContextException("contextualize(..) Exception", e);
            }
        }
    }

    /**
     * The <code>setLoggerManager</code> method will get a <code>LoggerManager</code>
     * for further use.
     *
     * @param loggerManager a <code>LoggerManager</code> value
     */
    public void setLoggerManager(LoggerManager loggerManager) {
        this.loggerManager = loggerManager;
        Deprecation.setLogger(this.loggerManager.getLoggerForCategory("deprecation"));
    }

    /**
     * Set the <code>InstrumentManager</code> for this Cocoon instance.
     *
     * @param manager an <code>InstrumentManager</code> instance
     */
    public void setInstrumentManager(final InstrumentManager manager) {
        this.instrumentManager = manager;
    }

    /**
     * The <code>initialize</code> method
     *
     * @exception Exception if an error occurs
     */
    public void initialize() throws Exception {
        if (parentComponentManager != null) {
            this.componentManager = new CocoonComponentManager(parentComponentManager,
                    (ClassLoader) this.context.get(Constants.CONTEXT_CLASS_LOADER));
        } else {
            this.componentManager = new CocoonComponentManager(
                    (ClassLoader) this.context.get(Constants.CONTEXT_CLASS_LOADER));
        }
        ContainerUtil.enableLogging(this.componentManager, this.rootLogger.getChildLogger("manager"));
        ContainerUtil.contextualize(this.componentManager, this.context);
        this.componentManager.setInstrumentManager(this.instrumentManager);
        getLogger().debug("New Cocoon object.");

        // Log the System Properties.
        dumpSystemProperties();

        // Setup the default parser, for parsing configuration.
        // If one need to use a different parser, set the given system property
        // first check for deprecated property to be compatible:
        String parser = getSystemProperty(Constants.DEPRECATED_PARSER_PROPERTY, Constants.DEFAULT_PARSER);
        if (!Constants.DEFAULT_PARSER.equals(parser)) {
            getLogger().warn("Deprecated property " + Constants.DEPRECATED_PARSER_PROPERTY + " is used. Please use "
                    + Constants.PARSER_PROPERTY + " instead.");
            if ("org.apache.cocoon.components.parser.XercesParser".equals(parser)) {
                parser = XercesParser.class.getName();
            } else {
                getLogger().warn("Unknown value for deprecated property: " + Constants.DEPRECATED_PARSER_PROPERTY
                        + ", value: " + parser
                        + ". If you experience problems during startup, check the parser configuration section of the documentation.");
            }
        } else {
            parser = getSystemProperty(Constants.PARSER_PROPERTY, Constants.DEFAULT_PARSER);
        }
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Parser: " + parser);
            getLogger().debug("Classpath: " + classpath);
            getLogger().debug("Work directory: " + workDir.getCanonicalPath());
        }

        ExcaliburComponentManager startupManager = new ExcaliburComponentManager(
                (ClassLoader) this.context.get(Constants.CONTEXT_CLASS_LOADER));
        ContainerUtil.enableLogging(startupManager, this.rootLogger.getChildLogger("startup"));
        ContainerUtil.contextualize(startupManager, this.context);
        startupManager.setLoggerManager(this.loggerManager);

        try {
            startupManager.addComponent(SAXParser.ROLE, ClassUtils.loadClass(parser),
                    new DefaultConfiguration("", "empty"));
        } catch (Exception e) {
            throw new ConfigurationException("Could not load parser " + parser, e);
        }

        ContainerUtil.initialize(startupManager);
        configure(startupManager);
        ContainerUtil.dispose(startupManager);
        startupManager = null;

        // add the logger manager to the component locator
        final ComponentProxyGenerator proxyGenerator = new ComponentProxyGenerator();
        final Component loggerManagerProxy = proxyGenerator.getProxy(LoggerManager.class.getName(), loggerManager);
        componentManager.addComponentInstance(LoggerManager.ROLE, loggerManagerProxy);

        ContainerUtil.initialize(this.componentManager);

        // Get the Processor and keep it if it's ThreadSafe
        Processor processor = (Processor) this.componentManager.lookup(Processor.ROLE);
        if (processor instanceof ThreadSafe) {
            if (getLogger().isDebugEnabled()) {
                getLogger().debug("Processor of class " + processor.getClass().getName() + " is ThreadSafe");
            }
            this.threadSafeProcessor = processor;
        } else {
            if (getLogger().isDebugEnabled()) {
                getLogger().debug("Processor of class " + processor.getClass().getName()
                        + " is NOT ThreadSafe -- will be looked up at each request");
            }
            this.componentManager.release(processor);
        }

        this.sourceResolver = (SourceResolver) this.componentManager.lookup(SourceResolver.ROLE);

        if (this.componentManager.hasComponent(RequestListener.ROLE)) {
            this.requestListener = (RequestListener) this.componentManager.lookup(RequestListener.ROLE);
        }
    }

    /** Dump System Properties */
    private void dumpSystemProperties() {
        if (getLogger().isDebugEnabled()) {
            try {
                Enumeration e = System.getProperties().propertyNames();
                getLogger().debug("===== System Properties Start =====");
                for (; e.hasMoreElements();) {
                    String key = (String) e.nextElement();
                    getLogger().debug(key + "=" + System.getProperty(key));
                }
                getLogger().debug("===== System Properties End =====");
            } catch (SecurityException se) {
                // Ignore Exceptions.
            }
        }
    }

    /**
     * Configure this <code>Cocoon</code> instance.
     *
     * @param startupManager an <code>ExcaliburComponentManager</code> value
     * @exception ConfigurationException if an error occurs
     * @exception ContextException if an error occurs
     */
    public void configure(ExcaliburComponentManager startupManager)
            throws ConfigurationException, ContextException {
        SAXParser p = null;
        Settings settings = SettingsHelper.getSettings(this.context);

        Configuration roles = null;
        try {
            p = (SAXParser) startupManager.lookup(SAXParser.ROLE);
            SAXConfigurationHandler b = new PropertyAwareSAXConfigurationHandler(settings, getLogger());
            URL url = ClassUtils.getResource("org/apache/cocoon/cocoon.roles");
            InputSource is = new InputSource(url.openStream());
            is.setSystemId(url.toString());
            p.parse(is, b);
            roles = b.getConfiguration();
        } catch (Exception e) {
            throw new ConfigurationException("Error trying to load configurations", e);
        } finally {
            if (p != null)
                startupManager.release((Component) p);
        }

        DefaultRoleManager drm = new DefaultRoleManager();
        ContainerUtil.enableLogging(drm, this.rootLogger.getChildLogger("roles"));
        ContainerUtil.configure(drm, roles);
        roles = null;

        try {
            this.configurationFile.refresh();
            p = (SAXParser) startupManager.lookup(SAXParser.ROLE);
            SAXConfigurationHandler b = new PropertyAwareSAXConfigurationHandler(settings, getLogger());
            InputSource is = SourceUtil.getInputSource(this.configurationFile);
            p.parse(is, b);
            this.configuration = b.getConfiguration();
        } catch (Exception e) {
            throw new ConfigurationException("Error trying to load configurations", e);
        } finally {
            if (p != null)
                startupManager.release((Component) p);
        }

        Configuration conf = this.configuration;
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Root configuration: " + conf.getName());
        }
        if (!"cocoon".equals(conf.getName())) {
            throw new ConfigurationException("Invalid configuration file\n" + conf.toString());
        }
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Configuration version: " + conf.getAttribute("version"));
        }
        if (!Constants.CONF_VERSION.equals(conf.getAttribute("version"))) {
            throw new ConfigurationException(
                    "Invalid configuration schema version. Must be '" + Constants.CONF_VERSION + "'.");
        }

        String userRoles = conf.getAttribute("user-roles", "");
        if (!"".equals(userRoles)) {
            try {
                p = (SAXParser) startupManager.lookup(SAXParser.ROLE);
                SAXConfigurationHandler b = new PropertyAwareSAXConfigurationHandler(settings, getLogger());
                org.apache.cocoon.environment.Context context = (org.apache.cocoon.environment.Context) this.context
                        .get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
                URL url = context.getResource(userRoles);
                if (url == null) {
                    throw new ConfigurationException(
                            "User-roles configuration '" + userRoles + "' cannot be found.");
                }
                InputSource is = new InputSource(new BufferedInputStream(url.openStream()));
                is.setSystemId(url.toString());
                p.parse(is, b);
                roles = b.getConfiguration();
            } catch (Exception e) {
                throw new ConfigurationException("Error trying to load user-roles configuration", e);
            } finally {
                startupManager.release((Component) p);
            }

            DefaultRoleManager urm = new DefaultRoleManager(drm);
            ContainerUtil.enableLogging(urm, this.rootLogger.getChildLogger("roles").getChildLogger("user"));
            ContainerUtil.configure(urm, roles);
            roles = null;
            drm = urm;
        }

        this.componentManager.setRoleManager(drm);
        this.componentManager.setLoggerManager(this.loggerManager);

        getLogger().debug("Setting up components...");
        ContainerUtil.configure(this.componentManager, conf);
    }

    /**
     * Queries the class to estimate its ergodic period termination.
     *
     * @param date a <code>long</code> value
     * @return a <code>boolean</code> value
     */
    public boolean modifiedSince(long date) {
        return date < this.configurationFile.getLastModified();
    }

    /**
     * Helper method to retrieve system property.
     * Returns default value if SecurityException is caught.
     */
    public static String getSystemProperty(String property, String value) {
        try {
            return System.getProperty(property, value);
        } catch (SecurityException e) {
            System.err.println("Caught a SecurityException reading the system property '" + property + "';"
                    + " Cocoon will default to '" + value + "' value.");
            return value;
        }
    }

    /**
     * Sets required system properties.
     */
    protected void setSystemProperties() {
        try {
            // FIXME We shouldn't have to specify the SAXParser...
            // This is needed by Xalan2, it is used by org.xml.sax.helpers.XMLReaderFactory
            // to locate the SAX2 driver.
            if (getSystemProperty("org.xml.sax.driver", null) == null) {
                System.setProperty("org.xml.sax.driver", "org.apache.xerces.parsers.SAXParser");
            }
        } catch (SecurityException e) {
            // Ignore security exceptions
            System.out.println("Caught a SecurityException writing the system property: " + e);
        }

        try {
            // FIXME We shouldn't have to specify these. Needed to override jaxp implementation of weblogic.
            if (getSystemProperty("javax.xml.parsers.DocumentBuilderFactory", "").startsWith("weblogic")) {
                System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
                        "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
                System.setProperty("javax.xml.parsers.SAXParserFactory",
                        "org.apache.xerces.jaxp.SAXParserFactoryImpl");
            }
        } catch (SecurityException e) {
            // Ignore security exceptions
            System.out.println("Caught a SecurityException writing the system property: " + e);
        }
    }

    /**
     * Dispose this instance
     */
    public void dispose() {
        if (this.componentManager != null) {
            if (this.requestListener != null) {
                this.componentManager.release(this.requestListener);
            }
            this.componentManager.release(this.threadSafeProcessor);
            this.threadSafeProcessor = null;

            this.componentManager.release(this.sourceResolver);
            this.sourceResolver = null;

            ContainerUtil.dispose(this.componentManager);
            this.componentManager = null;
        }

        this.context = null;
        if (Cocoon.instance == this) {
            Cocoon.instance = null;
        }
        this.disposed = true;
    }

    /**
     * Log debug information about the current environment.
     *
     * @param environment an <code>Environment</code> value
     */
    protected void debug(Environment environment, boolean internal) {
        String lineSeparator = SystemUtils.LINE_SEPARATOR;
        Map objectModel = environment.getObjectModel();
        Request request = ObjectModelHelper.getRequest(objectModel);
        Session session = request.getSession(false);
        StringBuffer msg = new StringBuffer();
        msg.append("DEBUGGING INFORMATION:").append(lineSeparator);
        if (internal) {
            msg.append("INTERNAL ");
        }
        msg.append("REQUEST: ").append(request.getRequestURI()).append(lineSeparator).append(lineSeparator);
        msg.append("CONTEXT PATH: ").append(request.getContextPath()).append(lineSeparator);
        msg.append("SERVLET PATH: ").append(request.getServletPath()).append(lineSeparator);
        msg.append("PATH INFO: ").append(request.getPathInfo()).append(lineSeparator).append(lineSeparator);

        msg.append("REMOTE HOST: ").append(request.getRemoteHost()).append(lineSeparator);
        msg.append("REMOTE ADDRESS: ").append(request.getRemoteAddr()).append(lineSeparator);
        msg.append("REMOTE USER: ").append(request.getRemoteUser()).append(lineSeparator);
        msg.append("REQUEST SESSION ID: ").append(request.getRequestedSessionId()).append(lineSeparator);
        msg.append("REQUEST PREFERRED LOCALE: ").append(request.getLocale().toString()).append(lineSeparator);
        msg.append("SERVER HOST: ").append(request.getServerName()).append(lineSeparator);
        msg.append("SERVER PORT: ").append(request.getServerPort()).append(lineSeparator).append(lineSeparator);

        msg.append("METHOD: ").append(request.getMethod()).append(lineSeparator);
        msg.append("CONTENT LENGTH: ").append(request.getContentLength()).append(lineSeparator);
        msg.append("PROTOCOL: ").append(request.getProtocol()).append(lineSeparator);
        msg.append("SCHEME: ").append(request.getScheme()).append(lineSeparator);
        msg.append("AUTH TYPE: ").append(request.getAuthType()).append(lineSeparator).append(lineSeparator);
        msg.append("CURRENT ACTIVE REQUESTS: ").append(activeRequestCount).append(lineSeparator);

        // log all of the request parameters
        Enumeration e = request.getParameterNames();

        msg.append("REQUEST PARAMETERS:").append(lineSeparator).append(lineSeparator);

        while (e.hasMoreElements()) {
            String p = (String) e.nextElement();

            msg.append("PARAM: '").append(p).append("' ").append("VALUES: '");
            String[] params = request.getParameterValues(p);
            for (int i = 0; i < params.length; i++) {
                msg.append("[" + params[i] + "]");
                if (i != (params.length - 1)) {
                    msg.append(", ");
                }
            }

            msg.append("'").append(lineSeparator);
        }

        // log all of the header parameters
        Enumeration e2 = request.getHeaderNames();

        msg.append("HEADER PARAMETERS:").append(lineSeparator).append(lineSeparator);

        while (e2.hasMoreElements()) {
            String p = (String) e2.nextElement();

            msg.append("PARAM: '").append(p).append("' ").append("VALUES: '");
            Enumeration e3 = request.getHeaders(p);
            while (e3.hasMoreElements()) {
                msg.append("[" + e3.nextElement() + "]");
                if (e3.hasMoreElements()) {
                    msg.append(", ");
                }
            }

            msg.append("'").append(lineSeparator);
        }

        msg.append(lineSeparator).append("SESSION ATTRIBUTES:").append(lineSeparator).append(lineSeparator);

        // log all of the session attributes
        if (session != null) {
            // Fix bug #12139: Session can be modified while still
            // being enumerated here
            synchronized (session) {
                e = session.getAttributeNames();
                while (e.hasMoreElements()) {
                    String p = (String) e.nextElement();
                    msg.append("PARAM: '").append(p).append("' ").append("VALUE: '").append(session.getAttribute(p))
                            .append("'").append(lineSeparator);
                }
            }
        }

        getLogger().debug(msg.toString());
    }

    /**
     * Process the given <code>Environment</code> to produce the output.
     *
     * @param environment an <code>Environment</code> value
     * @return a <code>boolean</code> value
     * @exception Exception if an error occurs
     */
    public boolean process(Environment environment) throws Exception {
        if (this.disposed) {
            throw new IllegalStateException("You cannot process a Disposed Cocoon engine.");
        }

        Object key = CocoonComponentManager.startProcessing(environment);
        final int environmentDepth = CocoonComponentManager.markEnvironment();
        CocoonComponentManager.enterEnvironment(environment, this.componentManager, this);
        try {
            boolean result;
            if (getLogger().isDebugEnabled()) {
                ++activeRequestCount;
                debug(environment, false);
            }

            if (this.requestListener != null) {
                try {
                    requestListener.onRequestStart(environment);
                } catch (Exception e) {
                    getLogger().error("Error encountered monitoring request start: " + e.getMessage());
                }
            }

            if (this.threadSafeProcessor != null) {
                result = this.threadSafeProcessor.process(environment);
                if (this.requestListener != null) {
                    try {
                        requestListener.onRequestEnd(environment);
                    } catch (Exception e) {
                        getLogger().error("Error encountered monitoring request start: " + e.getMessage());
                    }
                }
            } else {
                Processor processor = (Processor) this.componentManager.lookup(Processor.ROLE);
                try {
                    result = processor.process(environment);
                    if (this.requestListener != null) {
                        try {
                            requestListener.onRequestEnd(environment);
                        } catch (Exception e) {
                            getLogger().error("Error encountered monitoring request start: " + e.getMessage());
                        }
                    }
                } finally {
                    this.componentManager.release(processor);
                }
            }
            // commit response on success
            environment.commitResponse();

            return result;
        } catch (Exception any) {
            if (this.requestListener != null) {
                try {
                    requestListener.onRequestException(environment, any);
                } catch (Exception e) {
                    getLogger().error("Error encountered monitoring request start: " + e.getMessage());
                }
            }
            // reset response on error
            environment.tryResetResponse();
            throw any;
        } finally {
            CocoonComponentManager.leaveEnvironment();
            CocoonComponentManager.endProcessing(environment, key);
            if (getLogger().isDebugEnabled()) {
                --activeRequestCount;
            }

            // TODO (CZ): This is only for testing - remove it later on
            CocoonComponentManager.checkEnvironment(environmentDepth, getLogger());
        }
    }

    /**
     * Process the given <code>Environment</code> to assemble
     * a <code>ProcessingPipeline</code>.
     * @since 2.1
     */
    public ProcessingPipeline buildPipeline(Environment environment) throws Exception {
        if (disposed) {
            throw new IllegalStateException("You cannot process a Disposed Cocoon engine.");
        }

        try {
            if (getLogger().isDebugEnabled()) {
                ++activeRequestCount;
                debug(environment, true);
            }

            if (this.threadSafeProcessor != null) {
                return this.threadSafeProcessor.buildPipeline(environment);
            } else {
                Processor processor = (Processor) this.componentManager.lookup(Processor.ROLE);
                try {
                    return processor.buildPipeline(environment);
                } finally {
                    this.componentManager.release(processor);
                }
            }

        } finally {
            if (getLogger().isDebugEnabled()) {
                --activeRequestCount;
            }
        }
    }

    /**
     * Get the sitemap component configurations
     * @since 2.1
     */
    public Map getComponentConfigurations() {
        return Collections.EMPTY_MAP;
    }

    /**
     * Return this (Cocoon is always at the root of the processing chain).
     * @since 2.1.1
     */
    public Processor getRootProcessor() {
        return this;
    }

    /**
     * Accessor for active request count
     */
    public int getActiveRequestCount() {
        return activeRequestCount;
    }

    public ExcaliburComponentManager getComponentManager() {
        return this.componentManager;
    }

    /**
    * Create a simple source resolver.
    */
    protected SourceResolver createSourceResolver(Logger logger) throws ContextException {
        // Create our own resolver
        final SimpleSourceResolver resolver = new SimpleSourceResolver();
        resolver.enableLogging(logger);
        try {
            resolver.contextualize(this.context);
        } catch (ContextException ce) {
            throw new ContextException("Cannot setup source resolver.", ce);
        }
        return resolver;
    }
}