be.ff.gui.web.struts.action.ActionPlugInChain.java Source code

Java tutorial

Introduction

Here is the source code for be.ff.gui.web.struts.action.ActionPlugInChain.java

Source

/*
 * Struts Action Plug-in Extension.
 * Copyright (C) 2002 ASQdotCOM NV (http://www.asqdotcom.be/)
 *
 * This extension is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This extension is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
package be.ff.gui.web.struts.action;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import br.gov.camara.util.actionplugin.ActionPluginUtil;

/**
 * An instance of this class is passed into an <code>ActionPlugIn</code>'s <code>execute</code> method, enabeling the
 * plug-in developer to access the invocation chain of action plug-ins, during a request for a Struts action.
 * 
 * <p>
 * <code>ActionPlugIn</code>s use the <code>ActionPlugInChain</code> to invoke the next plug-in in the chain, or if the
 * calling plug-in is the last plug-in in the chain, to invoke the Struts action at the end of the chain.
 * </p>
 *
 * @author Gerrie Kimpen
 *
 * @see ActionPlugIn
 * @since FF 1.0
 */
public class ActionPlugInChain {
    private static Log log = LogFactory.getLog(ActionPlugInChain.class);

    // chain attributes
    private static List activeActionPlugInRegister = null;
    private static List activeActionPlugInDefinitionRegister = null;

    private int registerIndex = -1;

    private static boolean inicializado = false;

    /**
     * This static method initializes the action plug-in chain, by instantiating and initializing all configured
     * <code>ActionPlugIn</code> classes. This method must be called before the action plug-in mechanism comes into
     * action. Therefore it will be called in the <code>ActionPlugInPlugIn</code> class, which executes at application
     * start-up.
     *
     * @param chainDef the <code>ActionPlugInChainDefinition</code> instance that is used to initialize the chain and
     *        the configured action plug-ins
     * @param context the <code>ServletContext</code> instance used to initialize the configured action plug-ins
     */
    protected static void init(ActionPlugInChainDefinition chainDef, ServletContext context) {
        if (inicializado) {
            if (log.isDebugEnabled()) {
                log.debug("O ActionPlugInChain j foi inicializado anteriormente. Ignorando.");
            }
            return;
        }

        if (log.isDebugEnabled()) {
            log.debug("[ActionPlugInChain::init] Intializing the action plug-in chain ...");
        }
        activeActionPlugInRegister = new ArrayList();
        activeActionPlugInDefinitionRegister = new ArrayList();

        // loop through all configured action plug-ins
        List plugInDefs = chainDef.getActionPlugInDefintions();
        Iterator iter = plugInDefs.iterator();
        while (iter.hasNext()) {
            ActionPlugInDefinition def = (ActionPlugInDefinition) iter.next();

            try {
                // create an instance of the action plug-in class
                if (log.isDebugEnabled()) {
                    log.debug("[ActionPlugInChain::init] Instantiating '" + def.getClassName()
                            + "' action plug-in ...");
                }
                ActionPlugIn actionPlugIn = null;
                actionPlugIn = (ActionPlugIn) Class.forName(def.getClassName()).newInstance();

                try {
                    // initialize action plug-in instance
                    if (log.isDebugEnabled()) {
                        log.debug("[ActionPlugInChain::init] Initializing '" + def.getClassName()
                                + "' action plug-in ...");
                    }
                    ActionPlugInConfig config = new ActionPlugInConfig(def, context);
                    actionPlugIn.init(config);

                    // add this action plug-in to the list of active plug-ins
                    addActivePlugIn(actionPlugIn, def);
                } catch (ActionPlugInException e) {
                    String errorMsg = "[ActionPlugInChain::init] The initialization of the '" + def.getClassName()
                            + "' action plug-in failed. This action plug-in it will not be placed into service.";
                    Throwable cause = (e.getRootCause() != null) ? e.getRootCause() : e;
                    log.error(errorMsg, cause);
                }
            } catch (Exception e) {
                // InstantiationException, IllegalAccessException, ClassNotFoundException
                String errorMsg = "[ActionPlugInChain::init] The instantiation of the '" + def.getClassName()
                        + "' action plug-in failed. This action plug-in it will not be placed into service.";
                log.error(errorMsg, e);
            }
        }
        inicializado = true;
    }

    /**
     * This static method calls the <code>destroy</code> method on all <code>ActionPlugIn</code>s in the chain,
     * enabling them to release any referenced resources.
     */
    protected static void destroy() {
        if (log.isDebugEnabled()) {
            log.debug("[ActionPlugInChain::init] Destroying the action plug-in chain ...");
        }

        ListIterator iter = activeActionPlugInRegister.listIterator();
        while (iter.hasNext()) {
            ActionPlugIn actionPlugIn = (ActionPlugIn) iter.next();
            actionPlugIn.destroy();
        }
    }

    /**
     * This method calls <code>execute</code> method of the <code>ActionPlugIn</code> instance that is next in the
     * chain. Typically this method is called inside an <code>ActionPlugIn</code>'s <code>execute</code> method when
     * it is finished performing its logic and wants to pass control to the next <code>ActionPlugIn</code> in the
     * chain.
     * 
     * <p>
     * This method returns the <code>ActionForward</code> instance that is returned by one of the
     * <code>ActionPlugIn</code> instances in the chain, or <code>null</code> when none of the registered action
     * plug-ins decided to return an <code>ActionForward</code> instance. In the latter case the targetted Struts
     * action will be executed.
     * </p>
     *
     * @param mapping the <code>ActionMapping</code> instance, as provided by the Struts framework
     * @param form the <code>ActionForm</code> instance, as provided by the Struts framework
     * @param request the <code>HttpServletRequest</code> instance, as provided by the Struts framework
     * @param response the <code>HttpServletResponse</code> instance, as provided by the Struts framework
     *
     * @return an <code>ActionForward</code> instance or <code>null</code>
     *
     * @throws ActionPlugInException when a plug-in in the chain fails to execute for some reason
     */
    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
            HttpServletResponse response) throws ActionPlugInException {
        if (log.isDebugEnabled()) {
            log.debug("Entrada no mtodo");
        }

        ActionPlugIn actionFilter = getNextActionFilter(mapping, request);
        if (actionFilter == null) {
            if (log.isDebugEnabled()) {
                log.debug(
                        "No more plug-ins to execute. The chain has reached it last element and no ActionForward where issued. This means that the targetted Struts action will soon execute.");
            }

            /* No more plug-ins to execute. The chain has reached it last element
             and no ActionForward where issued. This means that the targetted
             Struts action will soon execute. */
            return null;
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Pass control to the next plug-in in the chain.");
            }

            // pass control to the next plug-in in the chain
            ActionForward acfProximoForward = null;

            acfProximoForward = actionFilter.execute(mapping, form, request, response, this);

            if (acfProximoForward == null && registerIndex < activeActionPlugInRegister.size()) {
                if (log.isErrorEnabled()) {
                    log.error("O forward especificado no foi encontrado.");
                }
                throw new ActionPlugInException("O forward especificado no foi encontrado.");
            }

            return acfProximoForward;
        }
    }

    /**
     * Adds the action plug-in and its accompanying defintion to the register of active action plug-ins.
     *
     * @param actionPlugIn the <code>ActionPlugIn</code> instance that will be registered
     * @param def the <code>ActionPlugInDefinition</code> instance that defines this <code>actionPlugIn</code>
     */
    private static void addActivePlugIn(ActionPlugIn actionPlugIn, ActionPlugInDefinition def) {
        if (log.isDebugEnabled()) {
            log.debug("Entrada no mtodo");
        }

        // add this action plug-in to the list of active plug-ins
        activeActionPlugInRegister.add(actionPlugIn);
        activeActionPlugInDefinitionRegister.add(def);
    }

    /**
     * Returns the next plug-in in the chain, that has not executed yet and that is not disabled for this action.
     *
     * @param mapping the <code>ActionMapping</code> as provided by the Struts framework
     *
     * @return the next <code>ActionPlugIn</code> in the chain, that has not executed yet
     */
    private ActionPlugIn getNextActionFilter(ActionMapping mapping, HttpServletRequest request) {
        // the action path for the current action
        String currentActionPath = ActionPluginUtil.getActionPath(request);

        if (currentActionPath == null) {
            String requestURL = request.getRequestURI();
            currentActionPath = requestURL.substring(requestURL.lastIndexOf('/'));
            currentActionPath = currentActionPath.substring(0, currentActionPath.lastIndexOf('.'));
            log.warn("'getRequestURL() == null' / 'getRequestURI() == " + requestURL
                    + "' ==>  Verificar se est correto !!!");
        }

        if (log.isDebugEnabled()) {
            log.debug("Avaliando o mapping.getPath()='" + mapping.getPath() + "' / actionPath='" + currentActionPath
                    + "'...");
        }

        ActionPlugIn nextActionPlugIn = null;
        while (nextActionPlugIn == null) {
            ActionPlugInDefinition nextDef = null;

            if (++registerIndex < activeActionPlugInRegister.size()) {
                nextDef = (ActionPlugInDefinition) activeActionPlugInDefinitionRegister.get(registerIndex);
            } else {
                break;
            }

            if (nextDef != null) {
                boolean ativaPlugin = false;

                // Plugin DESABILITADO para a ao em questo ?
                // Boolean plugInDisabledForAction = nextDef.hasDisabledActionPath(currentActionPath);
                if (!currentActionPath.equals(mapping.getPath())) {
                    log.warn("mapping.getPath()='" + mapping.getPath() + "'  diferente de actionPath='"
                            + currentActionPath + "'.");
                }
                Boolean plugInDisabledForAction = nextDef.hasDisabledActionPath(mapping.getPath());
                if (log.isDebugEnabled()) {
                    log.debug("... para a definio=" + nextDef.getClassName() + ", desabilitado="
                            + plugInDisabledForAction);
                }

                if (plugInDisabledForAction == null) {
                    // Plugin HABILITADO para a ao em questo ?
                    Boolean plugInEnabledForAction = nextDef.hasEnabledActionPath(currentActionPath);
                    if (log.isDebugEnabled()) {
                        log.debug("... para a definio=" + nextDef.getClassName() + ", habilitado="
                                + plugInEnabledForAction);
                    }

                    if (plugInEnabledForAction != null && plugInEnabledForAction.booleanValue()) {
                        // Ativar plugin
                        ativaPlugin = true;
                    }
                } else if (!plugInDisabledForAction.booleanValue()) {
                    // Ativar plugin
                    ativaPlugin = true;
                }

                if (ativaPlugin) {
                    nextActionPlugIn = (ActionPlugIn) activeActionPlugInRegister.get(registerIndex);
                }
            }
        }

        if (log.isDebugEnabled()) {
            log.debug("nextActionPlugIn=" + nextActionPlugIn);
        }

        return nextActionPlugIn;
    }

    public static boolean foiInicializado() {
        return inicializado;
    }
}