org.jboss.dashboard.ui.panel.PanelDriver.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.dashboard.ui.panel.PanelDriver.java

Source

/**
 * Copyright (C) 2012 JBoss Inc
 *
 * 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.jboss.dashboard.ui.panel;

import org.jboss.dashboard.Application;
import org.jboss.dashboard.LocaleManager;
import org.jboss.dashboard.commons.cdi.CDIBeanLocator;
import org.jboss.dashboard.database.hibernate.HibernateTxFragment;
import org.jboss.dashboard.commons.text.JavaNamesFormatter;
import org.jboss.dashboard.ui.NavigationManager;
import org.jboss.dashboard.ui.SessionManager;
import org.jboss.dashboard.ui.UIServices;
import org.jboss.dashboard.ui.components.BeanDispatcher;
import org.jboss.dashboard.ui.components.BeanHandler;
import org.jboss.dashboard.ui.controller.RequestContext;
import org.jboss.dashboard.ui.controller.responses.ShowPanelPage;
import org.jboss.dashboard.ui.formatters.FactoryURL;
import org.jboss.dashboard.ui.controller.CommandRequest;
import org.jboss.dashboard.ui.controller.CommandResponse;
import org.jboss.dashboard.ui.controller.responses.ShowCurrentScreenResponse;
import org.jboss.dashboard.ui.panel.parameters.*;
import org.jboss.dashboard.users.UserStatus;
import org.jboss.dashboard.workspace.*;
import org.jboss.dashboard.ui.components.panelManagement.ShowPanelConfigComponent;
import org.jboss.dashboard.ui.components.panelManagement.ShowPanelPageComponent;
import org.jboss.dashboard.ui.controller.responses.PanelAjaxResponse;
import org.jboss.dashboard.ui.controller.responses.ShowJSPAjaxResponse;
import org.jboss.dashboard.security.PanelPermission;
import org.jboss.dashboard.security.WorkspacePermission;
import org.jboss.dashboard.security.PanelSecurity;
import org.jboss.dashboard.security.SectionPermission;
import org.jboss.dashboard.ui.utils.javascriptUtils.JavascriptTree;
import org.hibernate.Session;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.enterprise.context.ApplicationScoped;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.Permission;
import java.util.*;

/**
 * This is the basic implementation for a functional panel driver, providing support
 * for all required services. Every Driver has to subclass
 * PanelDriver, and implement just it's own actions.
 * <p/>
 * This class also provides some useful services and shortcuts to make panel
 * developments easier.
 */
@ApplicationScoped
public class PanelDriver {

    public final static String PAGE_MANAGE_INVALID_DRIVER = "manage_invalid_panel_driver";
    public final static String PAGE_HELP_MODE = "page_help_mode";
    public final static String PAGE_SHOW = "show";
    public final static String PAGE_EDIT = "edit";
    public final static String PAGE_HEADER = "header";
    public final static String PARAMETER_ACTION_EXECUTED_ENABLED = "actionExecutedEnabled";

    /**
     * Logger
     */
    private static transient Logger log = LoggerFactory.getLogger(PanelDriver.class.getName());

    /**
     * Parameters definitions to be supplied to the panel
     */
    protected List<PanelProviderParameter> parameters = new ArrayList<PanelProviderParameter>();

    /**
     * Security table
     */
    protected PanelSecurity panelSecurity;

    /**
     * Returns all the parameters this panel driver allows to configure.
     */
    public PanelProviderParameter[] getAllParameters() {
        return parameters.toArray(new PanelProviderParameter[parameters.size()]);
    }

    /**
     * Adds a parameter for this panel driver. This method is intended to be called from the init method.
     *
     * @param parameter Parameter to add.
     */
    protected void addParameter(PanelProviderParameter parameter) {
        parameter.setSystemParameter(false);
        doAddParameter(parameter);
    }

    /**
     * Adds an array of parameters for this panel driver. This method is intended to be called from the init method.
     *
     * @param parameters Parameters to add.
     */
    protected void addParameters(PanelProviderParameter[] parameters) {
        for (PanelProviderParameter parameter : parameters) {
            addParameter(parameter);
        }
    }

    private void doAddParameter(PanelProviderParameter parameter) {
        Properties properties = parameter.getProvider().getProperties();
        String parameterId = parameter.getId();
        if (parameter.isI18n()) {
            LocaleManager localeManager = LocaleManager.lookup();
            String[] langs = localeManager.getPlatformAvailableLangs();
            for (String lang : langs) {
                String defaultValueInLang = properties
                        .getProperty("parameter." + parameterId + "." + lang + ".default");
                if (!StringUtils.isEmpty(defaultValueInLang))
                    parameter.setDefaultValue(defaultValueInLang, lang);
            }
        } else if (!properties.containsKey("parameter." + parameterId)) {
            parameter.setDefaultValue(
                    properties.getProperty("parameter." + parameterId + ".default", parameter.getDefaultValue()));
        }
        parameters.remove(parameter);
        parameters.add(parameter);
    }

    /**
     * Adds a system parameter.
     *
     * @param parameter Parameter to add
     */
    protected void addSystemParameter(PanelProviderParameter parameter) {
        parameter.setSystemParameter(true);
        doAddParameter(parameter);
    }

    /**
     * Adds a security restriction to a method in this panel.
     *
     * @param methodName      Method name
     * @param permissionClass Type of permission to apply before invoking it
     * @param action          action on the resource indicated by the permission
     * @throws NoSuchMethodException
     */
    protected void addMethodPermission(String methodName, Class permissionClass, String action)
            throws NoSuchMethodException {
        if (panelSecurity == null)
            panelSecurity = new PanelSecurity();
        //This is to verify that method exists
        this.getClass().getMethod(methodName, new Class[] { Panel.class, CommandRequest.class });
        panelSecurity.addMethodPermission(methodName, permissionClass, action);
    }

    /**
     * Called on provider initialization. Subclasses should override it to add custom parameters. Be sure to call super()
     * if you override it.
     *
     * @param provider Panel provider for this driver.
     */
    public void init(PanelProvider provider) throws Exception {
        initSystemParameters(provider);
        initPermissionsParameters();
    }

    protected void initSystemParameters(PanelProvider provider) {
        log.debug("Init driver. Adding system parameters");
        addSystemParameter(new StringParameter(provider, PanelInstance.PARAMETER_GROUP, false, false));
        addSystemParameter(new StringParameter(provider, PanelInstance.PARAMETER_TITLE, true, true));
        addParameter(new HTMLTextAreaParameter(provider, PanelInstance.PARAMETER_HTML_BEFORE, false, true));
        addParameter(new HTMLTextAreaParameter(provider, PanelInstance.PARAMETER_HTML_AFTER, false, true));

        // Probably will be deleted but not decided yet.
        //addSystemParameter(new IntParameter(provider, PanelInstance.PARAMETER_HEIGHT, true, "0"));
        //addSystemParameter(new BooleanParameter(provider, PanelInstance.PARAMETER_MAXIMIZABLE, false, false));
        //addSystemParameter(new BooleanParameter(provider, PanelInstance.PARAMETER_MINIMIZABLE, false, false));
        //addSystemParameter(new BooleanParameter(provider, PanelInstance.PARAMETER_PAINT_TITLE, false, false));
        //addSystemParameter(new BooleanParameter(provider, PanelInstance.PARAMETER_PAINT_BORDER, false, false));
        //addSystemParameter(new BooleanParameter(provider, PanelInstance.PARAMETER_SESSION_KEEP_ALIVE, false, false));
    }

    protected void initPermissionsParameters() throws NoSuchMethodException {
        Method[] methods = this.getClass().getMethods();
        for (Method method : methods) {
            if ((method.getName().startsWith("action") || method.getName().startsWith("panelAction"))
                    && method.getParameterTypes().length == 2 && method.getParameterTypes()[0].equals(Panel.class)
                    && method.getParameterTypes()[1].equals(CommandRequest.class)
                    && CommandResponse.class.equals(method.getReturnType())) {

                addMethodPermission(method.getName(), PanelPermission.class, PanelPermission.ACTION_VIEW);
                if ("panelActionEditMode".equals(method.getName()))
                    addMethodPermission(method.getName(), PanelPermission.class, PanelPermission.ACTION_EDIT);
                if ("panelActionMaximize".equals(method.getName()))
                    addMethodPermission(method.getName(), PanelPermission.class, PanelPermission.ACTION_MAXIMIZE);
                if ("panelActionMinimize".equals(method.getName()))
                    addMethodPermission(method.getName(), PanelPermission.class, PanelPermission.ACTION_MINIMIZE);
                if ("panelActionMoveBack".equals(method.getName()))
                    addMethodPermission(method.getName(), WorkspacePermission.class,
                            WorkspacePermission.ACTION_ADMIN);
                if ("panelActionMoveForward".equals(method.getName()))
                    addMethodPermission(method.getName(), WorkspacePermission.class,
                            WorkspacePermission.ACTION_ADMIN);
                if ("panelActionRemove".equals(method.getName()))
                    addMethodPermission(method.getName(), WorkspacePermission.class,
                            WorkspacePermission.ACTION_ADMIN);
                if ("panelActionResourcePreview".equals(method.getName()))
                    addMethodPermission(method.getName(), PanelPermission.class, PanelPermission.ACTION_EDIT);
                if ("panelActionResourcePreviewConfirm".equals(method.getName()))
                    addMethodPermission(method.getName(), PanelPermission.class, PanelPermission.ACTION_EDIT);
                if ("panelActionResourcesMode".equals(method.getName()))
                    addMethodPermission(method.getName(), PanelPermission.class, PanelPermission.ACTION_EDIT);
                if ("panelActionRestore".equals(method.getName()))
                    addMethodPermission(method.getName(), PanelPermission.class, PanelPermission.ACTION_MINIMIZE);
            }
        }
    }

    /**
     * Called on panel initialization
     *
     * @param instance PanelInstance where the panel belongs.
     * @throws Exception
     */
    public void initPanel(PanelInstance instance) throws Exception {
    }

    /**
     * Return the panel session related to this panel.
     *
     * @param panel
     * @return The panel session related to this panel.
     */
    public PanelSession getPanelSession(Panel panel) {
        return panel.getPanelSession();
    }

    /**
     * @deprecated use getPanelSession(Panel panel)
     */
    public PanelSession getPanelSession(CommandRequest req, Panel panel) {
        return panel.getPanelSession();
    }

    /**
     * @deprecated use getPanelSession(Panel panel)
     */
    public PanelSession getPanelSession(HttpServletRequest req, Panel panel) {
        return panel.getPanelSession();
    }

    /**
     * Called before dispatching to an action method
     *
     * @param panel
     * @param request
     * @return Null if the action execution can continue, or a CommandResponse if not
     */
    protected CommandResponse beforeInvokeAction(Panel panel, CommandRequest request) {
        LayoutRegionStatus regionStatus = SessionManager.getRegionStatus(panel.getSection(), panel.getRegion());
        PanelSession panelStatus = getPanelSession(panel);

        if (regionStatus != null) {
            regionStatus.setSelectedPanel(panel);

            if (panelStatus.isMinimized()) {
                panelStatus.setStatus(PanelSession.STATUS_REGULAR_SIZE);
            }
        }
        return null;
    }

    /**
     * Called after executing an action method
     *
     * @param panel
     * @param request
     * @param actionResponse Panel response
     * @return same panel response or a different one if any condition makes it necessary a different response
     */
    protected CommandResponse afterInvokeAction(Panel panel, CommandRequest request,
            CommandResponse actionResponse) {
        return actionResponse;
    }

    /**
     * Called before render the panel.
     *
     * @param panel
     * @param request
     * @param response
     */
    protected void beforeRenderPanel(Panel panel, HttpServletRequest request, HttpServletResponse response) {
        PanelProviderParameter[] params = panel.getProvider().getDriver().getAllParameters();
        String lang = LocaleManager.currentLang();
        for (PanelProviderParameter param : params) {
            String paramId = param.getId();
            String value = panel.getParameterValue(paramId);
            if (param.isI18n()) {
                String valueInCurrentLang = panel.getParameterValue(paramId, lang);
                value = StringUtils.isEmpty(valueInCurrentLang) ? value : valueInCurrentLang;
            }
            request.setAttribute(paramId, value);
        }
    }

    /**
     * Called after panel has been redered
     *
     * @param panel
     * @param request
     */
    protected void afterRenderPanel(Panel panel, HttpServletRequest request, HttpServletResponse response) {
        PanelParameter[] panelParameters = panel.getInstance().getPanelParameters();
        for (PanelParameter panelParameter : panelParameters) {
            request.removeAttribute(panelParameter.getIdParameter());
        }
        PanelSession session = panel.getPanelSession();
        session.setAttribute(PARAMETER_ACTION_EXECUTED_ENABLED, Boolean.TRUE);
    }

    /**
     * @deprecated use the version without session, and create your txFragment if needed.
     */
    protected void beforePanelInstanceRemove(PanelInstance instance, Session session) throws Exception {
        beforePanelInstanceRemove(instance);
    }

    /**
     * Called when a panel instance is removed from the system. This is to
     * allow the driver to cleanup any data attached to this panel instance, if needed.
     * Subclasses implementing this method must first call to super.
     *
     * @param instance Panel which is about to be removed
     */
    protected void beforePanelInstanceRemove(PanelInstance instance) throws Exception {
        // Empty panel dir, if needed
        try {
            File dir = getPanelDir(instance);
            log.debug("Directory to delete is " + dir.getCanonicalPath());
            if (dir.exists()) {
                log.debug("Emptying panel directory " + dir.getCanonicalPath());
                // Empty directory
                recursiveDelete(dir);
            }
        } catch (IOException e) {
            log.error("Error removing panel", e);
        }
    }

    /**
     * Fires in the same transaction, just before a panel is closed
     *
     * @param panel panel closed
     */
    protected void beforePanelClosed(Panel panel) {

    }

    /**
     * Fires in the same transaction, just after a panel is closed
     *
     * @param panel panel closed
     */
    protected void afterPanelClosed(Panel panel) throws Exception {
    }

    /**
     * Fires in the same transaction, just after a panel is closed
     *
     * @param panel panel closed
     */
    public void fireAfterPanelClosed(Panel panel) throws Exception {
        afterPanelClosed(panel);
    }

    /**
     * Fires before the panel is removed
     *
     * @param panel
     */
    protected void beforePanelRemoved(Panel panel) throws Exception {

    }

    /**
     * Fires in the same transaction, just before a panel is put in a region
     *
     * @param panel   panel closed
     * @param newRegion region where the panel is being placed
     */
    protected void beforePanelPlacedInRegion(Panel panel, LayoutRegion newRegion) {

    }

    /**
     * Fires in the same transaction, just after a panel is put in a region
     *
     * @param panel   panel closed
     * @param oldRegion region where the panel was before being moved.
     */
    protected void afterPanelPlacedInRegion(Panel panel, LayoutRegion oldRegion) throws Exception {
    }

    /**
     * Called when the a panel properties have been manually modified
     *
     * @param instance
     */
    protected void afterPanelPropertiesModified(PanelInstance instance) {
        JavascriptTree.regenerateTrees(instance.getWorkspace().getId());
    }

    /**
     * Called when the a panel custom properties have been manually modified
     *
     * @param instance
     */
    protected void afterPanelCustomPropertiesModified(PanelInstance instance) {
    }

    /*
     *
     * Actions shared by all panels (they may be overriden by subclasses)
     *
     */

    /**
     * Maximizes the panel
     */
    public CommandResponse panelActionMaximize(Panel panel, CommandRequest request) {
        log.debug("Maximizing panel " + panel.getPanelId());
        getPanelSession(panel).setStatus(PanelSession.STATUS_MAXIMIZED);
        return new ShowPanelPage();
    }

    /**
     * Maximizes the panel in region
     */
    public CommandResponse panelActionMaximizeInRegion(Panel panel, CommandRequest request) {
        log.debug("Maximizing panel in region " + panel.getPanelId());
        getPanelSession(panel).setStatus(PanelSession.STATUS_MAXIMIZED_IN_REGION);
        return new ShowPanelPage();
    }

    /**
     * Minimizes the panel
     */
    public CommandResponse panelActionMinimize(Panel panel, CommandRequest request) {
        log.debug("Minimizing panel " + panel.getPanelId());
        getPanelSession(panel).setStatus(PanelSession.STATUS_MINIMIZED);
        return new ShowPanelPage();
    }

    /**
     * Restores the panel to its regular size
     */
    public CommandResponse panelActionRestore(Panel panel, CommandRequest request) {
        log.debug("Restoring panel " + panel.getPanelId());
        getPanelSession(panel).setStatus(PanelSession.STATUS_REGULAR_SIZE);
        return new ShowPanelPage();
    }

    /**
     * Sets the panel in show mode
     */
    public CommandResponse panelActionShowMode(Panel panel, CommandRequest request) throws Exception {
        log.debug("Setting panel in configuration mode " + panel.getPanelId());
        activateNormalMode(panel, request);
        return new ShowPanelPage();
    }

    /**
     * Sets the panel in edit mode
     */
    public CommandResponse panelActionEditMode(Panel panel, CommandRequest request) throws Exception {
        if (supportsEditMode(panel)) {
            log.debug("Setting panel in edit mode " + panel.getPanelId());
            activateEditMode(panel, request);
        }
        return new ShowPanelPage();
    }

    /**
     * Sets the panel in help management mode
     */
    public CommandResponse panelActionHelpMode(Panel panel, CommandRequest request) throws Exception {
        if (supportsHelpMode(panel)) {
            log.debug("Setting panel in help mode " + panel.getPanelId());
            activateHelpMode(panel, request);
        }
        return new ShowPanelPage();
    }

    public CommandResponse panelActionStartConfig(Panel panel, CommandRequest request) throws Exception {
        log.debug("Setting panel in config mode " + panel.getPanelId());
        activateConfigMode(panel, request);
        return new ShowPanelPage();
    }

    protected String getPageHelpMode(Panel panel) {
        return PAGE_HELP_MODE;
    }

    protected String getPageEdit(Panel panel) {
        return PAGE_EDIT;
    }

    public void activateHelpMode(Panel panel, CommandRequest request) throws Exception {
        getPanelSession(panel).setWorkMode(PanelSession.HELP_MODE);
        getShowPanelPageComponent().openDialog(panel, request, getPageHelpMode(panel),
                getActionsBundle().getString("title.help"), getHelpWidth(panel, request),
                getHelpHeight(panel, request));
    }

    public int getHelpWidth(Panel panel, CommandRequest request) {
        return 800;
    }

    public int getHelpHeight(Panel panel, CommandRequest request) {
        return 600;
    }

    /**
     * Defines the action to be taken when activating edit mode
     *
     * @param panel
     * @param request
     */
    public void activateNormalMode(Panel panel, CommandRequest request) throws Exception {
        getPanelSession(panel).setWorkMode(PanelSession.SHOW_MODE);
        getShowPanelPageComponent().closePopup();
    }

    /**
     * Defines the action to be taken when activating edit mode
     *
     * @param panel
     * @param request
     */
    public void activateEditMode(Panel panel, CommandRequest request) throws Exception {
        getPanelSession(panel).setWorkMode(PanelSession.EDIT_MODE);
        getShowPanelPageComponent().openDialog(panel, request, getPageEdit(panel),
                getActionsBundle().getString("title.edit"), getEditWidth(panel, request),
                getEditHeight(panel, request));
    }

    public int getEditWidth(Panel panel, CommandRequest request) {
        return 800;
    }

    public int getEditHeight(Panel panel, CommandRequest request) {
        return 600;
    }

    public void activateConfigMode(Panel panel, CommandRequest request) throws Exception {
        getPanelSession(panel).setWorkMode(PanelSession.CONFIGURATION_MODE);
        getShowPanelConfigComponent().openDialog(panel, request, getActionsBundle().getString("title.edit"),
                getConfigWidth(panel, request), getConfigHeight(panel, request));
    }

    public int getConfigWidth(Panel panel, CommandRequest request) {
        return 800;
    }

    public int getConfigHeight(Panel panel, CommandRequest request) {
        return 600;
    }

    private ShowPanelConfigComponent getShowPanelConfigComponent() {
        return ShowPanelConfigComponent.lookup();
    }

    public ResourceBundle getActionsBundle() {
        return LocaleManager.lookup().getBundle("org.jboss.dashboard.ui.components.panelManagement.messages",
                LocaleManager.currentLocale());
    }

    /**
     * Removes panel from its region, but keeping it assigned to this section.
     */
    public CommandResponse panelActionClose(final Panel panel, CommandRequest request) {

        HibernateTxFragment txFragment = new HibernateTxFragment() {
            protected void txFragment(Session session) throws Exception {
                log.debug("Closing panel " + panel.getPanelId());
                beforePanelClosed(panel);
                Section section = panel.getSection();
                section.removePanelFromRegion(panel);
                UIServices.lookup().getSectionsManager().store(section);
                fireAfterPanelClosed(panel);
            }
        };

        try {
            txFragment.execute();
        } catch (Exception e) {
            log.error("Can't remove panel from region.", e);
        }
        return new ShowPanelPage();
    }

    /**
     * Moves panel backwards in its region
     */
    public CommandResponse panelActionMoveBack(final Panel panel, CommandRequest request) {

        HibernateTxFragment txFragment = new HibernateTxFragment() {
            protected void txFragment(Session session) throws Exception {
                Section section = NavigationManager.lookup().getCurrentSection();
                if (section != null)
                    section.moveBackInRegion(panel);
                UIServices.lookup().getSectionsManager().store(section);
            }
        };

        try {
            txFragment.execute();
        } catch (Exception e) {
            log.error("Can't move back panel in region.", e);
        }
        return new ShowPanelPage();
    }

    /**
     * Moves a panel from one region to another
     *
     * @param panel
     * @param regionName new region name
     */
    public void move(Panel panel, String regionName) throws Exception {
        Section section = panel.getSection();
        log.debug("Moving panel " + panel.getPanelId());

        if (regionName != null) {
            log.debug("Region name " + regionName);
            LayoutRegion oldRegion = panel.getRegion();
            LayoutRegion region = section.getLayout().getRegion(regionName);
            fireBeforePanelPlacedInRegion(panel, region);

            if (region != null) {
                log.debug("Moving panel to region " + region.getId());
                section.assignPanel(panel, region);
                if (oldRegion != null) {
                    LayoutRegionStatus status = SessionManager.getRegionStatus(panel.getSection(), oldRegion);
                    if (status.isSelected(panel)) {
                        status.setSelectedPanel(null);
                    }
                }
            }
            fireAfterPanelPlacedInRegion(panel, oldRegion);
        }

    }

    /**
     * Moves panel forward in its region
     */
    public CommandResponse panelActionMoveForward(final Panel panel, CommandRequest request) {
        HibernateTxFragment txFragment = new HibernateTxFragment() {
            protected void txFragment(Session session) throws Exception {
                Section section = NavigationManager.lookup().getCurrentSection();
                if (section != null)
                    section.moveForwardInRegion(panel);
                UIServices.lookup().getSectionsManager().store(section);
            }
        };
        try {
            txFragment.execute();
        } catch (Exception e) {
            log.error("Can't move forward panel in region.", e);
        }
        return new ShowPanelPage();
    }

    /**
     * Removes panel from system
     */
    public CommandResponse panelActionRemove(final Panel panel, CommandRequest request) {
        HibernateTxFragment txFragment = new HibernateTxFragment() {
            protected void txFragment(Session session) throws Exception {
                Section section = NavigationManager.lookup().getCurrentSection();
                if (section != null) {
                    section.removePanel(panel);
                    UIServices.lookup().getSectionsManager().store(section);
                }
            }
        };
        try {
            txFragment.execute();
        } catch (Exception e) {
            log.error("Panel " + panel.getPanelId() + " can't be removed.", e);
        }
        return new ShowPanelPage();
    }

    /**
     * Invalidates panel cache
     */
    public CommandResponse panelActionInvalidateCache(Panel panel, CommandRequest request) {
        // TODO: Invalidate panel cache here
        return new ShowPanelPage();
    }

    /**
     * Marks panel as selected in its region
     */
    public CommandResponse panelActionSelect(Panel panel, CommandRequest request) {
        LayoutRegionStatus regionStatus = SessionManager.getRegionStatus(panel.getSection(), panel.getRegion());
        PanelSession panelStatus = getPanelSession(panel);

        if (regionStatus != null) {
            regionStatus.setSelectedPanel(panel);

            if (panelStatus.isMinimized()) {
                panelStatus.setStatus(PanelSession.STATUS_REGULAR_SIZE);
            }
        }

        if (StringUtils.defaultString(request.getRequestObject().getHeader("user-agent")).contains("MSIE"))
            return new ShowPanelPage();

        return new ShowJSPAjaxResponse("/section/render_tabbed_region.jsp", panel.getRegion());
    }

    /**
     * Refresh a panel
     *
     * @param panel
     * @param request
     * @return ShowPanelPage
     */
    public CommandResponse panelActionRefreshPanel(Panel panel, CommandRequest request) {
        return new ShowPanelPage();
    }

    /**
     * Determine the method name for a given action parameter.<br>
     * Examples:
     * <li> start -> actionStart
     * <li> _start -> panelActionStart
     * <li> retrieve-file -> actionRetrieveFile
     * <li> retrieveFile -> actionRetrieveFile
     *
     * @param action Action to be performed
     * @return equivalent method name.
     */
    public static String getMethodName(String action) {
        String prefix;
        if (isSystemAction(action)) {
            // System commands
            prefix = "panel-action";
            action = action.substring(1);
        } else {
            prefix = "action";
        }
        return JavaNamesFormatter.toJavaName(prefix + "-" + action, false);
    }

    /**
     * Determine if given action is a system action (currently, if it starts with "_".
     *
     * @param action Action to process
     * @return true if it is a system action.
     */
    public static boolean isSystemAction(String action) {
        return action.startsWith("_");
    }

    /**
     * Execute an action on this panel.
     */
    public CommandResponse execute(Panel panel, CommandRequest req) throws Exception {
        try {
            RequestContext.lookup().activatePanel(panel);
            return _execute(panel, req);
        } finally {
            RequestContext.lookup().deactivatePanel(panel);
        }
    }

    protected CommandResponse _execute(Panel panel, CommandRequest req) throws Exception {
        String action = req.getRequestObject().getParameter(Parameters.DISPATCH_ACTION);
        PanelSession session = panel.getPanelSession();
        if (!isSystemAction(action) && !Boolean.TRUE.equals(session.getAttribute(PARAMETER_ACTION_EXECUTED_ENABLED))
                && isDoubleClickProtected(action)) {
            // Factory actions have their own double click control.
            log.warn(
                    "Discarding duplicated execution in panel " + panel.getInstance().getProvider().getDescription()
                            + ", action: " + action + ". User should be advised not to double click!");
            return new ShowPanelPage();
        }
        if (!isSystemAction(action)) {
            session.removeAttribute(PARAMETER_ACTION_EXECUTED_ENABLED);
        }

        // Get the panel's action method.
        String methodName = getMethodName(action);
        if (log.isDebugEnabled())
            log.debug("Invoking method " + methodName + " for class " + this.getClass().getName());
        Class[] params = { Panel.class, CommandRequest.class };
        Object[] args = { panel, req };
        Class cmdClass = this.getClass();
        Method method = cmdClass.getMethod(methodName, params);

        // Check the user has permission to access the panel.
        if (panelSecurity != null) {
            Set securityEntries = panelSecurity.entrySet(method.getName());
            for (Iterator it = securityEntries.iterator(); it.hasNext();) {
                PanelSecurity.PanelSecurityEntry entry = (PanelSecurity.PanelSecurityEntry) it.next();
                checkMethodSecurity(entry.getMethodName(), entry.getPermissionClass(), entry.getAction(), panel);
            }
        }
        // Invoke the panel's action method.
        CommandResponse res = null;
        if (!isSystemAction(action))
            res = fireBeforeInvokeAction(panel, req);
        if (res == null)
            res = (CommandResponse) method.invoke(this, args);
        if (!isSystemAction(action))
            res = fireAfterInvokeAction(panel, req, res);

        // If no AJAX then return the response get from panel invocation.
        String ajaxParam = req.getParameter(Parameters.AJAX_ACTION);
        if (ajaxParam == null || !Boolean.valueOf(ajaxParam).booleanValue())
            return res;

        // Despite the request was AJAX the panel has decided refreshing the full screen.
        if (res != null && res.getClass().equals(ShowCurrentScreenResponse.class))
            return res;

        // Else return the response wrapped as AJAX.
        PanelAjaxResponse response = PanelAjaxResponse.getEquivalentAjaxResponse(panel, res);
        if (response == null)
            log.error("Cannot convert response with " + res.getClass() + " to PanelAjaxResponse.");
        return response;
    }

    protected boolean isDoubleClickProtected(String action) {
        return true;
    }

    /**
     * Determine if an user can invoke an action in a panel based on permissions.
     *
     * @param panel Panel where action is to be invoked
     * @param action  Action to be performed
     * @return true if the user is allowed to execute the action.
     */
    public boolean canInvokeAction(Panel panel, String action) {
        String methodName = getMethodName(action);
        Set securityEntries = panelSecurity.entrySet(methodName);
        for (Iterator it = securityEntries.iterator(); it.hasNext();) {
            PanelSecurity.PanelSecurityEntry entry = (PanelSecurity.PanelSecurityEntry) it.next();
            if (!hasMethodAccess(methodName, entry.getPermissionClass(), entry.getAction(), panel))
                return false;
        }
        return true;
    }

    /**
     * Determine if an user can invoke an action in a panel based on permissions.
     *
     * @param panel Panel where action is to be invoked
     * @param action  Action to be performed
     */
    public void checkInvokeAction(Panel panel, String action) {
        String methodName = getMethodName(action);
        Set securityEntries = panelSecurity.entrySet(methodName);
        for (Iterator it = securityEntries.iterator(); it.hasNext();) {
            PanelSecurity.PanelSecurityEntry entry = (PanelSecurity.PanelSecurityEntry) it.next();
            checkMethodSecurity(entry.getMethodName(), entry.getPermissionClass(), entry.getAction(), panel);
        }
    }

    /**
     * @param methodName      Method to check
     * @param permissionClass Type of permission to check
     * @param action          Action to check
     * @param panel         Panel where action is to be invoked
     */
    protected void checkMethodSecurity(String methodName, Class permissionClass, String action, Panel panel) {
        try {
            Method instanceCreator = permissionClass.getMethod("newInstance",
                    new Class[] { Object.class, String.class });
            Permission perm = (Permission) instanceCreator.invoke(null,
                    new Object[] { getResourceForPermission(permissionClass, action, panel), action });
            UserStatus.lookup().checkPermission(perm);
        } catch (NoSuchMethodException e) {
            log.error("Error checking permission " + permissionClass.getName() + "[" + action + "] for method "
                    + methodName + ":", e);
        } catch (IllegalAccessException e) {
            log.error("Error checking permission " + permissionClass.getName() + "[" + action + "] for method "
                    + methodName + ":", e);
        } catch (InvocationTargetException e) {
            log.error("Error checking permission " + permissionClass.getName() + "[" + action + "] for method "
                    + methodName + ":", e);
        }
    }

    /**
     * Checks security for a method in a panel for givrn user.
     *
     * @param methodName      Method to check
     * @param permissionClass Type of permission to check
     * @param action          Action to check
     * @param panel         Panel where action is to be invoked
     * @return true if the user is allowed to execute the method.
     */
    protected boolean hasMethodAccess(String methodName, Class permissionClass, String action, Panel panel) {
        try {
            Method instanceCreator = permissionClass.getMethod("newInstance",
                    new Class[] { Object.class, String.class });
            Permission perm = (Permission) instanceCreator.invoke(null,
                    new Object[] { getResourceForPermission(permissionClass, action, panel), action });
            return UserStatus.lookup().hasPermission(perm);
        } catch (NoSuchMethodException e) {
            log.error("Error checking permission " + permissionClass.getName() + "[" + action + "] for method "
                    + methodName + ":", e);
        } catch (IllegalAccessException e) {
            log.error("Error checking permission " + permissionClass.getName() + "[" + action + "] for method "
                    + methodName + ":", e);
        } catch (InvocationTargetException e) {
            log.error("Error checking permission " + permissionClass.getName() + "[" + action + "] for method "
                    + methodName + ":", e);
        }
        return false;
    }

    /**
     * Determine the resource associated for a permission. For instance, if it is a PanelPermission, it will be the panel itself.
     *
     * @param permissionClass Type of permission
     * @param action          action being performed, may be used internally.
     * @param panel         current panel
     * @return The object where the permission applies, or null if none applies.
     */
    protected Object getResourceForPermission(Class permissionClass, String action, Panel panel) {
        if (permissionClass.equals(PanelPermission.class))
            return panel;
        if (permissionClass.equals(WorkspacePermission.class))
            return panel.getWorkspace();
        if (permissionClass.equals(SectionPermission.class))
            return panel.getSection();
        log.warn("Cannot determine resource where permission applies: " + permissionClass);
        return null;
    }

    /*
     *
     * Services and shortcuts to subclasses
     *
     */

    /**
     * Returns the directory where this panel can store its files. It will be automatically cleaned when the panel
     * is removed
     *
     * @param panelInstance Panel instance whose directory is retrieved
     * @return directory assigned to given panel
     * @throws Exception
     */
    protected File getPanelDir(PanelInstance panelInstance) throws Exception {
        String baseDir = Application.lookup().getBaseAppDirectory() + File.separator
                + panelInstance.getProvider().getPanelsDir();

        File dir = new File(baseDir + File.separator + panelInstance.getDbid());
        if (!dir.exists()) {
            //New directory format. Since 2.0.00
            dir = new File(baseDir + File.separator + panelInstance.getWorkspace().getId() + File.separator
                    + panelInstance.getInstanceId());
        }

        log.debug("getPanelDir() for instance dbid=" + panelInstance.getDbid() + " is " + dir.getCanonicalPath());
        if (!dir.exists()) {
            log.debug("Creating dir");
            if (!dir.mkdirs()) {
                throw new Exception("Can't create directory: " + dir.getCanonicalPath());
            }
        }

        return dir;
    }

    /**
     * Returns the directory where this panel can store its files. It will be automatically cleaned when the panel
     * is removed
     *
     * @param panel Panel whose directory is retrieved
     * @return directory assigned to given panel
     * @throws Exception
     */
    protected File getPanelDir(Panel panel) throws Exception {
        return getPanelDir(panel.getInstance());
    }

    /**
     * Returns the URL mapping used to reference the directory which holds the panel data
     *
     * @param panel Panel being attended
     * @return the URL mapping to the panel resources directory
     */
    protected String getPanelDirMapping(Panel panel) throws Exception {
        return getPanelDirMapping(panel.getInstance());
    }

    /**
     * Returns the URL mapping used to reference the directory which holds the panel data
     *
     * @param panelInstance PanelInstance being attended
     * @return the URL mapping to the panel resources directory
     */
    protected String getPanelDirMapping(PanelInstance panelInstance) throws Exception {
        String basePanelsDir = Application.lookup().getBaseAppDirectory() + File.separator
                + panelInstance.getProvider().getPanelsDir();

        File dir = new File(basePanelsDir + File.separator + panelInstance.getDbid());
        String urlMapping = panelInstance.getProvider().getPanelsUrlMapping();

        if (dir.exists()) {//old format
            return urlMapping + "/" + panelInstance.getInstanceId();
        }
        return urlMapping + "/" + panelInstance.getWorkspace().getId() + "/" + panelInstance.getInstanceId();
    }

    /**
     * Returns the URL to show when maximized, or null if none
     *
     * @param panelStatus
     * @return null
     * @deprecated It is of no practical use
     */
    public String getURLWhenMaximized(PanelSession panelStatus) {
        return null;
    }

    /**
     * Returns if this driver defines support to activate edit mode.
     *
     * @param panel
     * @return true if this driver defines support to activate resources mode.
     */
    public boolean supportsEditMode(Panel panel) {
        return false;
    }

    /**
     * Returns if this driver defines support to activate help mode.
     *
     * @param panel
     * @return true if this driver defines support to activate help mode.
     */
    public boolean supportsHelpMode(Panel panel) {
        return panel.getProvider().getPanelHelp() != null;
    }

    /**
     * Called on panel initialization (when a new PanelSession instance is created attached to a given session)
     */
    public void initPanelSession(PanelSession panelSession, HttpSession session) {
        panelSession.setCurrentPageId(PAGE_SHOW);
    }

    /**
     * Called before the panel is placed in a region
     *
     * @param panel panel being placed
     * @param region  region where the panel is being placed
     */
    public void fireBeforePanelPlacedInRegion(Panel panel, LayoutRegion region) {
        beforePanelPlacedInRegion(panel, region);
    }

    /**
     * Called after the panel is placed in a region
     *
     * @param panel panel being placed
     * @param region  region where the panel was before
     */
    public void fireAfterPanelPlacedInRegion(Panel panel, LayoutRegion region) throws Exception {
        afterPanelPlacedInRegion(panel, region);
    }

    /**
     * Called before the panel is removed
     *
     * @param panel panel being placed
     */
    public void fireBeforePanelRemoved(Panel panel) throws Exception {
        beforePanelRemoved(panel);
    }

    /**
     * Called before dispatching to an action method.
     *
     * @return Null if the action execution can continue, or a CommandResponse if not
     * @see PanelDriver#beforeInvokeAction(org.jboss.dashboard.workspace.Panel, org.jboss.dashboard.ui.controller.CommandRequest)
     */
    public CommandResponse fireBeforeInvokeAction(Panel panel, CommandRequest request) {
        return beforeInvokeAction(panel, request);
    }

    /**
     * Called after executing an action method
     *
     * @param panel
     * @param request
     * @param response
     * @return
     * @see PanelDriver#afterInvokeAction(org.jboss.dashboard.workspace.Panel, org.jboss.dashboard.ui.controller.CommandRequest, org.jboss.dashboard.ui.controller.CommandResponse)
     */
    public CommandResponse fireAfterInvokeAction(Panel panel, CommandRequest request, CommandResponse response) {
        return afterInvokeAction(panel, request, response);
    }

    /**
     * Called before render the panel.
     *
     * @param panel
     * @param request
     * @param response
     * @see PanelDriver#beforeRenderPanel
     */
    public void fireBeforeRenderPanel(Panel panel, HttpServletRequest request, HttpServletResponse response) {
        beforeRenderPanel(panel, request, response);
    }

    /**
     * Called after panel has been redered
     *
     * @param panel
     * @param request
     * @see PanelDriver#afterRenderPanel
     */
    public void fireAfterRenderPanel(Panel panel, HttpServletRequest request, HttpServletResponse response) {
        afterRenderPanel(panel, request, response);
    }

    /**
     * Called when a panel instance is removed from the system. This is to
     * allow the driver to cleanup any data atteched to this panel instance, if needed.
     *
     * @param instance Panel which is about to be removed
     * @see PanelDriver#beforePanelInstanceRemove
     */
    public void fireBeforePanelInstanceRemove(PanelInstance instance) throws Exception {
        beforePanelInstanceRemove(instance);
    }

    /**
     * Called when the a panel properties have been manually modified
     *
     * @param instance
     * @see PanelDriver#afterPanelPropertiesModified
     */
    public void firePanelPropertiesModified(PanelInstance instance) {
        afterPanelPropertiesModified(instance);
    }

    /**
     * Called when the a panel properties have been manually modified
     *
     * @param instance
     * @see PanelDriver#afterPanelPropertiesModified
     */
    public void firePanelCustomPropertiesModified(PanelInstance instance) {
        afterPanelCustomPropertiesModified(instance);
    }

    /**
     * Replicates panel data. Called when a workspace is duplicated.
     *
     * @param src  Source PanelInstance
     * @param dest Destinaton PanelInstance
     */
    public void replicateData(final PanelInstance src, final PanelInstance dest) throws Exception {
        // Default implementation. If the panel uses special tables or files, should overwrite this
        // to implement duplication of own data.
        File dirSrc = getPanelDir(src);
        File dirDest = getPanelDir(dest);
        log.debug("Copying directory tree from " + dirSrc.getCanonicalPath() + " to " + dirDest.getCanonicalPath());
        copyDirectory(dirSrc, dirDest);
    }

    protected void copyDirectory(File src, File dest) throws IOException {
        if (src.isFile()) {
            log.warn("File " + src + " is not a directory. Copying it as a file");
            copyFile(src, dest);
            return;
        }
        log.debug("Copying directory ");
        log.debug("   " + src);
        log.debug("to");
        log.debug("   " + dest);
        File[] files = src.listFiles();
        if (files == null) {
            log.warn("File " + src + " cannot contain files. Reasons: it is a file or it does not exist.");
            return;
        }
        dest.mkdirs();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            if (file.isFile()) {
                copyFile(file, new File(dest.getAbsolutePath() + File.separator + file.getName()));
            } else if (file.isDirectory()) {
                File fDest = new File(dest.getAbsolutePath() + File.separator + file.getName());
                copyDirectory(file, fDest);
            }
        }
    }

    protected void copyFile(File src, File dest) throws IOException {
        log.debug("Copying file ");
        log.debug("   " + src);
        log.debug("to");
        log.debug("   " + dest);
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(src));
            bos = new BufferedOutputStream(new FileOutputStream(dest));
            int byteRead;
            while ((byteRead = bis.read()) != -1) {
                bos.write(byteRead);
            }
        } finally {
            if (bos != null)
                bos.close();
            if (bis != null)
                bis.close();
        }
    }

    private void recursiveDelete(File f) {
        if (f.isDirectory()) {
            File[] files = f.listFiles();
            if (files != null) {
                for (File file : files) {
                    recursiveDelete(file);
                }
            }
            if (!f.delete())
                f.deleteOnExit();
        } else if (f.isFile()) {
            if (!f.delete())
                f.deleteOnExit();
        }
    }

    /**
     * Action that dispatches to a factory component.
     */
    public CommandResponse panelActionFactory(final Panel panel, CommandRequest request) throws Exception {
        BeanDispatcher requestHandler = CDIBeanLocator.getBeanByType(BeanDispatcher.class);
        CommandResponse factoryResponse = requestHandler.handleRequest(request);
        String action = request.getRequestObject().getParameter(FactoryURL.PARAMETER_ACTION);
        String beanName = request.getRequestObject().getParameter(FactoryURL.PARAMETER_BEAN);
        if (action != null) {
            BeanHandler handler = (BeanHandler) CDIBeanLocator.getBeanByNameOrType(beanName);
            if (handler != null)
                action = handler.getActionForShortcut(action);
            String methodName = getMethodName(action);
            Class[] params = { Panel.class, CommandRequest.class };
            Object[] args = { panel, request };
            Class cmdClass = this.getClass();
            Method method;
            try {
                method = cmdClass.getMethod(methodName, params);
                if (factoryResponse == null)
                    factoryResponse = (CommandResponse) method.invoke(this, args);
                else
                    method.invoke(this, args);
            } catch (NoSuchMethodException e) {
                if (log.isDebugEnabled())
                    log.debug("Method " + cmdClass.getName() + "." + methodName + "() not found");
            } catch (IllegalAccessException e) {
                log.error("Error: ", e);
            } catch (InvocationTargetException e) {
                log.error("Error: ", e);
            }
        }
        if (factoryResponse != null)
            return factoryResponse;
        return new ShowPanelPage();
    }

    /**
     * Action to change a page for a panel. It expects a parameter in request called "pageId"
     */
    public CommandResponse actionChangePage(final Panel panel, CommandRequest request) {
        String pageId = request.getParameter("pageId");
        if (pageId == null || "".equals(pageId)) {
            pageId = panel.getPanelSession().getCurrentPageId();
        }
        return new ShowPanelPage(panel, request, pageId);
    }

    public Map getTextShownByInstance(PanelInstance instance) {
        Map m = new HashMap();
        LocaleManager localeManager = LocaleManager.lookup();
        String[] langs = localeManager.getPlatformAvailableLangs();
        for (int i = 0; i < langs.length; i++) {
            String lang = langs[i];
            String before = instance.getParameterValue(PanelInstance.PARAMETER_HTML_BEFORE, lang);
            String panelBody = getPanelHTMLContent(instance, lang);
            String after = instance.getParameterValue(PanelInstance.PARAMETER_HTML_AFTER, lang);
            StringBuffer sb = new StringBuffer();
            if (!StringUtils.isEmpty(before))
                sb.append(before);
            if (!StringUtils.isEmpty(panelBody))
                sb.append(panelBody);
            if (!StringUtils.isEmpty(after))
                sb.append(after);
            String total = sb.toString().trim();
            if (!StringUtils.isEmpty(total)) {
                m.put(lang, total);
            }
        }
        return m.isEmpty() ? null : m;
    }

    protected String getPanelHTMLContent(PanelInstance instance, String lang) {
        return "";
    }

    public ShowPanelPageComponent getShowPanelPageComponent() {
        return ShowPanelPageComponent.lookup();
    }
}