Package org.apache.shale.remoting.impl

Source Code of org.apache.shale.remoting.impl.ChainProcessor

/*
* 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.shale.remoting.impl;

import java.io.IOException;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.CatalogFactory;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shale.remoting.Processor;

/**
* <p>Implementation of {@link Processor} which maps a resource identifier
* to the name of a <a href="http://commons.apache.org/chain">Commons
* Chain</a> command or chain, in an appropriate catalog.  The command or chain
* that is executed is passed an appropriate <code>Context</code> object, and
* it will also have access to the current JavaServer Faces state by calling
* <code>FacesContext.getCurrentInstance()</code>.</p>
*/
public class ChainProcessor implements Processor {


    // ------------------------------------------------------------ Constructors



    // ------------------------------------------------------ Instance Variables


    /**
     * <p>The <code>Log</code> instance for this class.</p>
     */
    private transient Log log = null;


    // ------------------------------------------------------- Processor Methods


    /**
     * <p>Map the specified resource identifier to an appropriate Commons
     * Chain command or chain, in an appropriate catalog.  Construct an
     * appropriate <code>Context</code> object, and execute the specified
     * command or chain, to which we delegate responsibility for creating
     * the response for the current request.  Call
     * <code>FacesContext.responseComplete()</code> to tell JavaServer Faces
     * that the entire response has already been created.</p>
     *
     * @param context <code>FacesContext</code> for the current request
     * @param resourceId Resource identifier used to select the appropriate response
     *  (this will generally be a context relative path starting with "/")
     *
     * @exception IOException if an input/output error occurs
     * @exception NullPointerException if <code>viewId</code> is <code>null</code>
     */
    public void process(FacesContext context, String resourceId) throws IOException {

        if (log().isDebugEnabled()) {
            log().debug("Translated resource id '" + resourceId + "' to catalog '"
                        + mapCatalog(context, resourceId) + "' and command '"
                        + mapCommand(context, resourceId) + "'");
        }

        // Identify the Commons Chain catalog we will be using
        String catalogName = mapCatalog(context, resourceId);
        Catalog catalog = CatalogFactory.getInstance().getCatalog(catalogName);
        if (catalog == null) {
            if (log().isErrorEnabled()) {
                log().error("Cannot find catalog '" + catalogName + "' for resource '"
                            + resourceId + "'");
            }
            sendNotFound(context, resourceId);
            context.responseComplete();
            return;
        }

        // Identify the Commons Chain chain or command we will be executing
        String commandName = mapCommand(context, resourceId);
        Command command = catalog.getCommand(commandName);
        if (command == null) {
            if (log().isErrorEnabled()) {
                log().error("Cannot find command '" + commandName + "' in catalog '"
                            + catalogName + "' for resource '" + resourceId + "'");
            }
            sendNotFound(context, resourceId);
            context.responseComplete();
            return;
        }

        // Create a new context and pass it to the specified command
        try {
            command.execute(createContext(context, resourceId));
        } catch (Exception e) {
            if (log().isErrorEnabled()) {
                log().error("Exception executing command '" + commandName
                            + "' from catalog '" + catalogName + "' for resource '"
                            + resourceId + "'", e);
            }
            sendServerError(context, resourceId, e);
        }

        // Tell JavaServer Faces that the current response has been completed
        context.responseComplete();

    }


    // ------------------------------------------------------- Protected Methods


    /**
     * <p>Create and return an appropriate <code>Context</code> instance to be
     * passed to the command or chain that is executed.</p>
     *
     * <p>The default algorithm constructs and returns an instance of
     * {@link ChainContext} that wraps the specified <code>FacesContext</code>.</p>
     *
     * @param context <code>FacesContext</code> for the current request
     * @param resourceId Resource identifier to be mapped
     */
    protected Context createContext(FacesContext context, String resourceId) {

        return new ChainContext(context);

    }


    /**
     * <p>Map the specified resource identifier to the name of a Commons Chain
     * <code>Catalog</code> from which the command or chain instance will be
     * acquired.</p>
     *
     * <p>The default implementation returns <code>remoting</code>
     * unconditionally.</p>
     *
     * @param context <code>FacesContext</code> for the current request
     * @param resourceId Resource identifier to be mapped
     */
    protected String mapCatalog(FacesContext context, String resourceId) {

        return "remoting";

    }


    /**
     * <p>Map the specified resource identifier to the name of a Commons Chain
     * <code>Command</code> or <code>Chain</code>, which will be acquired from
     * a mapped <code>Catalog</code>.</p>
     *
     * <p>The default algorithm performs this conversion as follows:</p>
     * <ul>
     * <li>Strip any leading slash character.</li>
     * <li>Convert embedded slash characters to periods.</li>
     * </ul>
     *
     * @param context <code>FacesContext</code> for the current request
     * @param resourceId Resource identifier to be mapped
     */
    protected String mapCommand(FacesContext context, String resourceId) {

        // Strip any leading slash character
        if (resourceId.startsWith("/")) {
            resourceId = resourceId.substring(1);
        }

        // Convert nested slash characters into periods
        resourceId = resourceId.replace('/', '.');

        // Return the resulting string
        return resourceId;

    }


    /**
     * <p>Send a "not found" HTTP response, if possible.  Otherwise, throw an
     * <code>IllegalArgumentException</code> that will ripple out.</p>
     *
     * @param context <code>FacesContext</code> for the current request
     * @param resourceId Resource identifier of the resource that was not found
     *
     * @exception IllegalArgumentException if we cannot send an HTTP response
     * @exception IOException if an input/output error occurs
     */
    protected void sendNotFound(FacesContext context, String resourceId) throws IOException {

        if (servletRequest(context)) {
            HttpServletResponse response = (HttpServletResponse)
              context.getExternalContext().getResponse();
            response.sendError(HttpServletResponse.SC_NOT_FOUND, resourceId);
        } else {
            throw new IllegalArgumentException(resourceId);
        }

    }


    /**
     * <p>Send a "server error" HTTP response, if possible.  Otherwise, throw a
     * <code>FacesException</code> that will ripple out.</p>
     *
     * @param context <code>FacesContext</code> for the current request
     * @param resourceId Resource identifier of the resource that was not found
     * @param e Server exception to be reported
     *
     * @exception FacesException if we cannot send an HTTP response
     * @exception IOException if an input/output error occurs
     */
    protected void sendServerError(FacesContext context, String resourceId,
                                   Exception e) throws IOException {

        if (servletRequest(context)) {
            HttpServletResponse response = (HttpServletResponse)
              context.getExternalContext().getResponse();
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, resourceId);
        } else {
            throw new FacesException(resourceId);
        }

    }


    /**
     * <p>Return <code>true</code> if we are processing a servlet request (as
     * opposed to a portlet request).</p>
     *
     * @param context <code>FacesContext</code> for the current request
     */
    protected boolean servletRequest(FacesContext context) {

        return context.getExternalContext().getContext() instanceof ServletContext;

    }


    // --------------------------------------------------------- Private Methods


    /**
     * <p>Return the <code>Log</code> instance to use, creating one if needed.</p>
     */
    private Log log() {

        if (this.log == null) {
            log = LogFactory.getLog(ChainProcessor.class);
        }
        return log;

    }


}
TOP

Related Classes of org.apache.shale.remoting.impl.ChainProcessor

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.