Package org.apache.cocoon.components.flow

Source Code of org.apache.cocoon.components.flow.AbstractInterpreter

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.flow;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Map;

import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.thread.SingleThreaded;
import org.apache.cocoon.Constants;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.components.flow.util.PipelineUtil;
import org.apache.cocoon.environment.Context;
import org.apache.cocoon.environment.Redirector;
import org.apache.excalibur.source.SourceUtil;

/**
* Abstract superclass for various scripting languages used by Cocoon
* for flow control. Defines some useful behavior like the ability to
* reload script files if they get modified (useful when doing
* development), and passing the control to Cocoon's sitemap for
* result page generation.
* <p>
* Flow intrepreters belonging to different sitemaps should be isolated. To achieve this,
* class implements the {@link org.apache.avalon.framework.thread.SingleThreaded}. Since
* the sitemap engine looks up the flow intepreter once at sitemap build time, this ensures
* that each sitemap will use a different instance of this class. But that instance will
* handle all flow calls for a given sitemap, and must therefore be thread safe.
*
* @author <a href="mailto:ovidiu@cup.hp.com">Ovidiu Predescu</a>
* @since March 15, 2002
* @version CVS $Id: AbstractInterpreter.java 433543 2006-08-22 06:22:54Z crossley $
*/
public abstract class AbstractInterpreter
        extends AbstractLogEnabled
        implements Component, Serviceable, Contextualizable, Interpreter,
                   SingleThreaded, Configurable, Disposable {

    // The instance ID of this interpreter, used to identify user scopes
    private String instanceID;

    protected org.apache.avalon.framework.context.Context avalonContext;

    /**
     * List of source locations that need to be resolved.
     */
    protected ArrayList needResolve = new ArrayList();

    protected org.apache.cocoon.environment.Context context;
    protected ServiceManager manager;
    protected ContinuationsManager continuationsMgr;

    /**
     * Whether reloading of scripts should be done. Specified through
     * the "reload-scripts" attribute in <code>flow.xmap</code>.
     */
    protected boolean reloadScripts;

    /**
     * Interval between two checks for modified script files. Specified
     * through the "check-time" XML attribute in <code>flow.xmap</code>.
     */
    protected long checkTime;

    public AbstractInterpreter() {
    }

    /**
     * Set the unique ID for this interpreter, which can be used to distinguish user value scopes
     * attached to the session.
     */
    public void setInterpreterID(String interpreterID) {
        this.instanceID = interpreterID;
    }

    /**
     * Get the unique ID for this interpreter, which can be used to distinguish user value scopes
     * attached to the session.
     *
     * @return a unique ID for this interpreter
     */
    public String getInterpreterID() {
        return this.instanceID;
    }

    public void configure(Configuration config) throws ConfigurationException {
        reloadScripts = config.getChild("reload-scripts").getValueAsBoolean(false);
        checkTime = config.getChild("check-time").getValueAsLong(1000L);
    }

    /**
     * Serviceable
     */
    public void service(ServiceManager sm) throws ServiceException {
        this.manager = sm;
        this.continuationsMgr = (ContinuationsManager)sm.lookup(ContinuationsManager.ROLE);
    }

    public void contextualize(org.apache.avalon.framework.context.Context context)
    throws ContextException{
        this.avalonContext = context;
        this.context = (Context)context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
    }

    /* (non-Javadoc)
     * @see org.apache.avalon.framework.activity.Disposable#dispose()
     */
    public void dispose() {
        if ( this.manager != null ) {
            this.manager.release( this.continuationsMgr );
            this.continuationsMgr = null;
            this.manager = null;
        }
    }

    /**
     * Registers a source file with the interpreter. Using this method
     * an implementation keeps track of all the script files which are
     * compiled. This allows them to reload the script files which get
     * modified on the file system.
     *
     * <p>The parsing/compilation of a script file by an interpreter
     * happens in two phases. In the first phase the file's location is
     * registered in the <code>needResolve</code> array.
     *
     * <p>The second is possible only when a Cocoon
     * <code>Environment</code> is passed to the Interpreter. This
     * allows the file location to be resolved using Cocoon's
     * <code>SourceFactory</code> class.
     *
     * <p>Once a file's location can be resolved, it is removed from the
     * <code>needResolve</code> array and placed in the
     * <code>scripts</code> hash table. The key in this hash table is
     * the file location string, and the value is a
     * DelayedRefreshSourceWrapper instance which keeps track of when
     * the file needs to re-read.
     *
     * @param source the location of the script
     *
     * @see org.apache.cocoon.environment.Environment
     * @see org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper
     */
    public void register(String source) {
        synchronized (this) {
            needResolve.add(source);
        }
    }

    /**
     * Call the Cocoon sitemap for the given URI, sending the output of the
     * eventually matched pipeline to the specified outputstream.
     *
     * @param uri The URI for which the request should be generated.
     * @param biz Extra data associated with the subrequest.
     * @param out An OutputStream where the output should be written to.
     * @exception Exception If an error occurs.
     */
    public void process(String uri, Object biz, OutputStream out)
    throws Exception {
        // FIXME (SW): should we deprecate this method in favor of PipelineUtil?
        PipelineUtil pipeUtil = new PipelineUtil();
        try {
            pipeUtil.contextualize(this.avalonContext);
            pipeUtil.service(this.manager);
            pipeUtil.processToStream(uri, biz, out);
        } finally {
            pipeUtil.dispose();
        }
    }

    public void forwardTo(String uri, Object bizData,
                          WebContinuation continuation,
                          Redirector redirector)
    throws Exception {
        if (SourceUtil.indexOfSchemeColon(uri) == -1) {
            uri = "cocoon:/" + uri;
            Map objectModel = ContextHelper.getObjectModel(this.avalonContext);
            FlowHelper.setWebContinuation(objectModel, continuation);
            FlowHelper.setContextObject(objectModel, bizData);
            if (redirector.hasRedirected()) {
                throw new IllegalStateException("Pipeline has already been processed for this request");
            }
            // this is a hint for the redirector
            objectModel.put("cocoon:forward", "true");
            redirector.redirect(false, uri);
        } else {
            throw new Exception("uri is not allowed to contain a scheme (cocoon:/ is always automatically used)");
        }
    }
}
TOP

Related Classes of org.apache.cocoon.components.flow.AbstractInterpreter

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.