com.adito.core.actions.AbstractMultiFormDispatchAction.java Source code

Java tutorial

Introduction

Here is the source code for com.adito.core.actions.AbstractMultiFormDispatchAction.java

Source

/*
*  Adito
*
*  Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
*
*  This program 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 of
*  the License, or (at your option) any later version.
*  This program 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.
*
*  You should have received a copy of the GNU General Public
*  License along with this program; if not, write to the Free Software
*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package com.adito.core.actions;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

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

import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.config.ActionConfig;
import org.apache.struts.config.FormBeanConfig;
import org.apache.struts.util.RequestUtils;

import com.adito.boot.Util;
import com.adito.core.DefaultPanel;
import com.adito.core.Panel;
import com.adito.core.PanelManager;
import com.adito.core.forms.AbstractMultiFormDispatchForm;
import com.adito.policyframework.Permission;
import com.adito.policyframework.ResourceType;
import com.adito.security.SessionInfo;

/**
 */
public abstract class AbstractMultiFormDispatchAction extends AuthenticatedDispatchAction {
    private final Map<String, AuthenticatedDispatchAction> actions = new HashMap<String, AuthenticatedDispatchAction>();
    private final int placement_;

    /**
     * Constructor
     * 
     * @param resourceType
     * @param permissions
     * @param placement
     */
    public AbstractMultiFormDispatchAction(ResourceType resourceType, Permission permissions[], int placement) {
        super(resourceType, permissions);
        placement_ = placement;
    }

    @SuppressWarnings("unchecked")
    protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request,
            HttpServletResponse response, String name) throws Exception {
        Collection<Panel> panels = PanelManager.getInstance().getPanels(placement_, request, response,
                DefaultPanel.MAIN_LAYOUT);
        Collection<SubActionWrapper> subActions = getSubActions(mapping, form, request, panels);

        AbstractMultiFormDispatchForm dispatchForm = (AbstractMultiFormDispatchForm) form;
        dispatchForm.init(subActions, mapping, request);

        ActionForward fwd = provideActionTargets(subActions, dispatchForm, request, response, name);
        if (fwd != null) {
            return fwd;
        }

        // Now do the normal dispatch handling. This is what determines the
        // forward
        if (null == name)
            return unspecified(mapping, form, request, response);

        return getActionForward(mapping, form, request, response, name);
    }

    private Collection<SubActionWrapper> getSubActions(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, Collection<Panel> panels) throws ClassNotFoundException,
            IllegalAccessException, InstantiationException, InvocationTargetException {
        Collection<SubActionWrapper> subActions = new ArrayList<SubActionWrapper>();
        int index = 0;
        for (Panel panel : panels) {
            /*
             * First get all of the availble action mappings and create all of
             * the forms First try to find the panels action config. Look for
             * the same name as the panel id prefixed by a /
             */
            ActionConfig config = mapping.getModuleConfig().findActionConfig("/" + panel.getId());
            if (null != config && config instanceof ActionMapping) {
                ActionMapping subMapping = (ActionMapping) config;
                SubActionWrapper subActionWrapper = getSubActionWrapper(mapping, form, subMapping, request, index);
                if (null != subActionWrapper)
                    subActions.add(subActionWrapper);
            }
            index++;
        }
        return subActions;
    }

    private static SubActionWrapper getSubActionWrapper(ActionMapping mapping, ActionForm form,
            ActionMapping subMapping, HttpServletRequest request, int index) throws ClassNotFoundException,
            IllegalAccessException, InstantiationException, InvocationTargetException {
        String formName = subMapping.getName();
        ActionForm subForm = getActionForm(subMapping, request);

        FormBeanConfig formBean = mapping.getModuleConfig().findFormBeanConfig(formName);
        String className = formBean == null ? null : formBean.getType();
        if (className == null)
            return null;

        if (subForm == null || !className.equals(subForm.getClass().getName()))
            subForm = (ActionForm) Class.forName(className).newInstance();

        if ("request".equals(mapping.getScope()))
            request.setAttribute(formName, subForm);
        else
            request.getSession().setAttribute(formName, subForm);

        subForm.reset(mapping, request);

        /*
         * We dont want to try and populate all forms on a post, only the one
         * that has requested it. For this the form must have a hidden parameter
         * with the name of 'subForm' and the value being the form name to
         * populate
         */
        AbstractMultiFormDispatchForm dispatchForm = (AbstractMultiFormDispatchForm) form;
        if (formName.equals(dispatchForm.getSubForm())) {
            dispatchForm.setSelectedTab(dispatchForm.getTabName(index));
            BeanUtils.populate(subForm, request.getParameterMap());
        }

        return new SubActionWrapper(subForm, subMapping);
    }

    private static ActionForm getActionForm(ActionMapping subMapping, HttpServletRequest request) {
        String formName = subMapping.getName();
        if ("request".equals(subMapping.getScope()))
            return (ActionForm) request.getAttribute(formName);
        else
            return (ActionForm) request.getSession().getAttribute(formName);
    }

    private ActionForward provideActionTargets(Collection<SubActionWrapper> subActions,
            AbstractMultiFormDispatchForm dispatchForm, HttpServletRequest request, HttpServletResponse response,
            String name)
            throws ClassNotFoundException, IOException, IllegalAccessException, InstantiationException {
        if (null == name || name.equals(""))
            name = "unspecified";
        // JDR added the ability to refresh all sub forms.
        boolean refreshAll = new Boolean(request.getParameter("refreshAll"));

        String subForm = dispatchForm.getSubForm();
        ActionForm subform = (ActionForm) request.getSession().getAttribute(subForm);
        ActionForward fwd = null;

        // Now try to create actions and run the provided action target on each.
        // Any forwards returned are ignored
        for (SubActionWrapper wrapper : subActions) {
            try {
                // We have an action config, so get the action instance
                Action action = processActionCreate(request, response, wrapper.getMapping());
                // Identify the method object to be dispatched to
                if (dispatchForm.isSubFormEmpty() || wrapper.getForm().equals(subform) || refreshAll) {
                    Method method = getMethod(action, name);
                    Object args[] = { wrapper.getMapping(), wrapper.getForm(), request, response };
                    // Invoke the method. We don't care about the forward
                    // returned,
                    // it will not be used.
                    if (wrapper.getForm().equals(subform)) {
                        fwd = (ActionForward) method.invoke(action, args);
                    } else {
                        method.invoke(action, args);
                    }
                }
            } catch (Exception e) {
                log.error(e);
            }
        }

        return fwd;
    }

    private Method getMethod(Action action, String name) throws NoSuchMethodException {
        synchronized (methods) {
            String methodName = action.getClass().getName() + "#" + name;
            if (!methods.containsKey(methods)) {
                Method method = action.getClass().getMethod(name, types);
                methods.put(methodName, method);
            }
            return (Method) methods.get(methodName);
        }
    }

    private Action processActionCreate(HttpServletRequest request, HttpServletResponse response,
            ActionConfig mapping)
            throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        synchronized (actions) {
            String className = mapping.getType();
            if (!actions.containsKey(className)) {
                if (log.isTraceEnabled())
                    log.trace("  Creating new Action instance");
                AuthenticatedDispatchAction instance = (AuthenticatedDispatchAction) RequestUtils
                        .applicationInstance(className);
                instance.setServlet(servlet);
                actions.put(className, instance);
            }
            return actions.get(className);
        }
    }

    private ActionForward getActionForward(ActionMapping mapping, ActionForm form, HttpServletRequest request,
            HttpServletResponse response, String name) throws Exception {
        try {
            Method method = getMethod(name);
            Object args[] = { mapping, form, request, response };
            return (ActionForward) method.invoke(this, args);
        } catch (ClassCastException e) {
            log.error(getMessage(mapping, name, "dispatch.return"), e);
            throw e;
        } catch (IllegalAccessException e) {
            log.error(getMessage(mapping, name, "dispatch.error"), e);
            throw e;
        } catch (NoSuchMethodException e) {
            return unspecified(mapping, form, request, response);
        } catch (InvocationTargetException e) {
            Throwable t = e.getTargetException();
            if (t instanceof Exception) {
                throw (Exception) t;
            } else {
                log.error(getMessage(mapping, name, "dispatch.error"), e);
                throw new ServletException(t);
            }
        }
    }

    private static String getMessage(ActionMapping mapping, String name, String message) {
        return messages.getMessage(message, mapping.getPath(), name);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.struts.actions.DispatchAction#unspecified(org.apache.struts.action.ActionMapping,
     *      org.apache.struts.action.ActionForm,
     *      javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse)
     */
    public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        return mapping.findForward("display");
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.adito.core.actions.CoreAction#getNavigationContext(org.apache.struts.action.ActionMapping,
     *      org.apache.struts.action.ActionForm,
     *      javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse)
     */
    public int getNavigationContext(ActionMapping mapping, ActionForm form, HttpServletRequest request,
            HttpServletResponse response) {
        return SessionInfo.MANAGEMENT_CONSOLE_CONTEXT;
    }

    public static final class SubActionWrapper {
        private final ActionForm form_;
        private final ActionMapping mapping_;

        SubActionWrapper(ActionForm form, ActionMapping mapping) {
            form_ = form;
            mapping_ = mapping;
        }

        public ActionForm getForm() {
            return form_;
        }

        public ActionMapping getMapping() {
            return mapping_;
        }
    }
}