/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2009 Bull S.A.S
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.webapp.jonasadmin.service.container;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.ow2.jonas.lib.management.extensions.base.BaseManagement;
import org.ow2.jonas.lib.management.extensions.container.ContainerManagement;
import org.ow2.jonas.lib.management.extensions.container.ejb.EjbItemByNameComparator;
import org.ow2.jonas.management.extensions.base.api.ManagementException;
import org.ow2.jonas.webapp.jonasadmin.JonasAdminJmx;
import org.ow2.jonas.webapp.jonasadmin.JonasBaseAction;
import org.ow2.jonas.webapp.jonasadmin.WhereAreYou;

/**
 * @author Michel-Ange ANTON
 */

public class EditContainerAction extends JonasBaseAction {

// --------------------------------------------------------- Public Methods

    @Override
    public ActionForward executeAction(final ActionMapping p_Mapping, final ActionForm p_Form
        , final HttpServletRequest p_Request, final HttpServletResponse p_Response)
        throws IOException, ServletException {

          // Current server
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        /**
         * Prepare to edit statistics on selected container.
         */
        m_Session.setAttribute("editAllContainers", "false");
        // Selected container
        String sObjectName = p_Request.getParameter("select");
        if (sObjectName == null) {
            // Accept request attribute forced by a EditEjbAction
            sObjectName = (String) p_Request.getAttribute("select");
        }
        // Get next forward if the access is throught a ejb else by default is null
        String sNextForward = (String) p_Request.getAttribute("NextForward");
        // Determine the ObjectName of the managed container (module)
        ObjectName oObjectName = null;
        try {
            if (sNextForward != null) {
                oObjectName = getModuleObjectName(sObjectName);
            } else {
                oObjectName = new ObjectName(sObjectName);
            }

            if (!BaseManagement.getInstance().isRegistered(oObjectName, serverName)) {
                refreshServicesTree(p_Request);
                return (p_Mapping.findForward("ActionListContainers"));
            }

        } catch (Throwable t) {
            addGlobalError(t);
            saveErrors(p_Request, m_Errors);
            return (p_Mapping.findForward("Global Error"));
        }


        // Form used
        ContainerForm oForm = null;
        String sPath = null;
        String parentName = null;
        // Build a new form
        if (oObjectName != null) {
            oForm = new ContainerForm();
            oForm.reset(p_Mapping, p_Request);
            m_Session.setAttribute("containerForm", oForm);
            URL url = (URL) BaseManagement.getInstance().getAttribute(oObjectName, "url", serverName);
            sPath = url.getPath();

            oForm.setPath(sPath);
            oForm.setFilename(JonasAdminJmx.extractFilename(sPath));
            oForm.setObjectName(oObjectName);


            boolean earSupport = true;
            try {
                Boolean b = (Boolean) BaseManagement.getInstance().getAttribute(oObjectName, "inEarCase", serverName);
            } catch (ManagementException noa) {
                Throwable cause = noa.getCause();
                if (cause.getClass().equals(javax.management.AttributeNotFoundException.class)) {
                    earSupport = false;
                }
            }

            if (earSupport) {
                oForm.setEarPath((URL) BaseManagement.getInstance().getAttribute(oObjectName, "earURL", serverName));
                oForm.setEarON(getStringAttribute(oObjectName, "earON"));
                parentName = oObjectName.getKeyProperty(WhereAreYou.J2EE_APPLICATION_KEY);
            }
        } else {
            // Used last form in session
            oForm = (ContainerForm) m_Session.getAttribute("containerForm");
        }

        // Force the node selected in tree only when no next forward
        if (sNextForward == null) {
            String fileName = oForm.getFilename();
            if (parentName != null && !"none".equals(parentName) && !"null".equals(parentName)) {
                fileName = parentName.concat(WhereAreYou.NODE_NAME_SEPARATOR + fileName);
            }
            m_WhereAreYou.selectNameNode(getTreeBranchName(DEPTH_SERVER)
                + WhereAreYou.NODE_SEPARATOR + "services" + WhereAreYou.NODE_SEPARATOR
                + "ejbContainers" + WhereAreYou.NODE_SEPARATOR + fileName, true);
        }

        // Populate
        if (oObjectName != null) {
            try {
                oForm.setObjectName(oObjectName);
                getStats(oForm, oObjectName, serverName);
                searchEjbs(oForm, sPath, oObjectName, serverName);
            } catch (Throwable t) {
                addGlobalError(t);
                saveErrors(p_Request, m_Errors);
                return (p_Mapping.findForward("Global Error"));
            }

            if ("true".equals(oObjectName.getKeyProperty("virtualContext"))) {
                sNextForward = "Ejb Virtual";
                String pServer = m_WhereAreYou.getCurrentJonasServerName();
                ObjectName versioningService;
                try {
                    versioningService = new ObjectName(oObjectName.getDomain() + ":type=service,name=versioning");
                } catch (Exception e) {
                    throw new ServletException("Cannot find the versioning service MBean", e);
                }
                String[] policies = (String[]) BaseManagement.getInstance().getAttribute(versioningService, "Policies", pServer);

                // Get contexts
                Map<String, String> contexts =
                    (Map<String, String>) BaseManagement.getInstance().getAttribute(oObjectName, "Contexts", pServer);

                // Set new contexts and refresh
                String[] opSignature = {"java.lang.String", "java.lang.String"};
                for (String context : contexts.keySet()) {
                    String policy = p_Request.getParameter(context);
                    if (policy != null) {
                        String[] opParams = {context, policy};
                        BaseManagement.getInstance().invoke(oObjectName, "rebindContext", opParams, opSignature, pServer);
                    }
                }
                contexts = (Map<String, String>) BaseManagement.getInstance().getAttribute(oObjectName, "Contexts", pServer);

                // Set attributes for the JSP
                oForm.setContexts(contexts);
                oForm.setPolicies(policies);
                p_Request.setAttribute("contexts", contexts);
                p_Request.setAttribute("policies", policies);
                p_Request.setAttribute("objectName", oObjectName);
            }
        } else {
            oForm.setObjectName(null);
            oForm.setContexts(null);
            oForm.setPolicies(null);
        }

        // Replace the normal forward if exists
        if (sNextForward == null) {
            sNextForward = "Container";
        }
        // Forward to the jsp
        return (p_Mapping.findForward(sNextForward));
    }

    protected void getStats(final ContainerForm form, final ObjectName objectName, final String serverName) {
        boolean ejb3 = false;
        String containerName = null;
        try {
            containerName = (String) BaseManagement.getInstance().getAttribute(objectName, "containerName", serverName);
        } catch (ManagementException noa) {
            Throwable cause = noa.getCause();
            if (cause.getClass().getName().equals("javax.management.AttributeNotFoundException")) {
                ejb3 = true;
                containerName = objectName.getKeyProperty("name");
            }
        }
        form.setContainerName(containerName);
        Map nbs = ContainerManagement.getInstance().getTotalEJB(objectName);
        int nbtotal = 0;
        int nb = (Integer) nbs.get("MessageDrivenBean");
        nbtotal = nbtotal + nb;
        form.setCurrentNumberOfMDBType(nb);
        nb = (Integer) nbs.get("StatefulSessionBean");
        nbtotal = nbtotal + nb;
        form.setCurrentNumberOfSBFType(nb);
        nb = (Integer) nbs.get("StatelessSessionBean");
        nbtotal =  nbtotal + nb;
        form.setCurrentNumberOfSBLType(nb);
        nb = (Integer) nbs.get("EntityBean");
        nbtotal = nbtotal +  nb;
        form.setCurrentNumberOfEntityType(nb);
        form.setCurrentNumberOfBeanType(nbtotal);
        form.setMonitoringEnabled(getBooleanAttribute(objectName, "monitoringEnabled"));
        form.setWarningThreshold(getIntegerAttribute(objectName, "warningThreshold"));
        form.setNumberOfCalls(getIntegerAttribute(objectName, "numberOfCalls"));
        form.setTotalBusinessProcessingTime(getLongAttribute(objectName, "totalBusinessProcessingTime"));
        form.setTotalProcessingTime(getLongAttribute(objectName, "totalProcessingTime"));
        form.setAverageBusinessProcessingTime(getLongAttribute(objectName, "averageBusinessProcessingTime"));
        form.setAverageProcessingTime(getLongAttribute(objectName, "averageProcessingTime"));
    }
    /**
     * Prepare Ejb list in this container
     * @param p_Form
     * @param p_Path
     * @param p_ObjectName
     * @param serverName
     * @throws Exception
     */
    protected void searchEjbs(final ContainerForm p_Form, final String p_Path, final ObjectName p_ObjectName, final String serverName)
        throws Exception {
        String sName;
        String sTypeResource;
        ArrayList al = new ArrayList();

        /**
         * Get entity beans.
         */
        List<?> entityBeans = ContainerManagement.getInstance().getEntityBeans(p_ObjectName, serverName);
        al.addAll(entityBeans);

        /**
         * Get Stateful Session Beans.
         */
        List<?> sfsb = ContainerManagement.getInstance().getStatefulSessionBeans(p_ObjectName, serverName);
        al.addAll(sfsb);

        /**
         * Get Stateless Session Beans.
         */
        List<?> slsb = ContainerManagement.getInstance().getStatelessSessionBeans(p_ObjectName, serverName);
        al.addAll(slsb);

        /**
         * Get Message Driven Beans.
         */
        List<?> mdb = ContainerManagement.getInstance().getMessageDrivenBeans(p_ObjectName, serverName);
        al.addAll(mdb);


        // Sort by name
        Collections.sort(al, new EjbItemByNameComparator());
        // Save in form
        p_Form.setEjbs(al);
    }
    /**
     * Gets ObjectName for J2EE Module.
     * @param ejbObjectName
     * @return module object name.
     * @throws MalformedObjectNameException
     */
    ObjectName getModuleObjectName(final String ejbObjectName) throws MalformedObjectNameException {
        return ContainerManagement.getInstance().getEJBModuleObjectName(ejbObjectName);
    }
}
