/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2003-2008 Bull S.A.
 * 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.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.management.ObjectName;

import org.ow2.jonas.lib.management.extensions.base.JonasManagementRepr;
import org.ow2.jonas.lib.management.javaee.J2eeObjectName;
import org.ow2.jonas.lib.util.JonasObjectName;
import org.ow2.jonas.webapp.jonasadmin.JonasAdminJmx;
import org.ow2.jonas.webapp.jonasadmin.deploy.BaseDeployAction;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionMapping;
/**
 * @author Michel-Ange ANTON
 * @author S. Ali Tokmen
 */

abstract public class BaseWebAppAction extends BaseDeployAction {

    // --------------------------------------------------------- Protected
    // variables

    protected WebAppForm mWebAppForm;

    protected WarForm mWarForm;

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

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

    /**
     * Initialize the forms and parameters.
     * @param p_Mapping Mapping to reset form
     * @param p_Request Http request used
     * @return true if the forms must be populated
     */
    protected boolean initialize(final ActionMapping p_Mapping, final HttpServletRequest p_Request) {

        boolean bPopulate = false;

        // Global form used
        mWebAppForm = null;
        mWarForm = null;

        // Action
        String sParamAction = p_Request.getParameter("action");
        // Selected WebApp (ObjectName)
        String sParamWebAppObjectName = p_Request.getParameter("on");
        // Selected War
        String sParamPathWar = p_Request.getParameter("war");

        // Detect create action
        if (sParamAction != null && "create".equals(sParamAction)) {
            // Create a new WebApp
            mWebAppForm = createWebAppForm(p_Mapping, p_Request);
            mWebAppForm.setAction("create");
            // Remove WarForm
            m_Session.removeAttribute("warForm");
        } else if (sParamWebAppObjectName != null) {
            // Build forms with the object name
            mWebAppForm = createWebAppForm(p_Mapping, p_Request);
            mWebAppForm.setObjectName(sParamWebAppObjectName);
            bPopulate = true;
            // Remove WarForm
            m_Session.removeAttribute("warForm");
        } else if (sParamPathWar != null) {
            // Create a new War form
            mWarForm = createWarForm(p_Mapping, p_Request);
            mWarForm.setPath(sParamPathWar);
            mWarForm.setFilename(JonasAdminJmx.extractFilename(sParamPathWar));
            bPopulate = true;
        } else {
            // Edit last form in session
            mWebAppForm = (WebAppForm) m_Session.getAttribute("webAppForm");
            if (mWebAppForm != null) {
                mWebAppForm.setAction("edit");
            }
            mWarForm = (WarForm) m_Session.getAttribute("warForm");
            // Force populate
            if (("reload".equals(sParamAction) == true) || ("start".equals(sParamAction) == true)
                    || ("stop".equals(sParamAction) == true)) {
                bPopulate = true;
            }
        }
        return bPopulate;
    }

    /**
     * Create a new WebApp form in function of Web Server.
     * @param p_Mapping Mapping to reset form
     * @param p_Request Http request used
     * @return The new form or null if web server unknown
     */
    protected WebAppForm createWebAppForm(final ActionMapping p_Mapping, final HttpServletRequest p_Request) {
        WebAppForm oForm = null;
        if (m_WhereAreYou.isCatalinaServer() == true) {
            boolean virtualContext;
            try {
                String sParamWebAppObjectName = p_Request.getParameter("on");
                ObjectName on = J2eeObjectName.getObjectName(sParamWebAppObjectName);
                virtualContext = "true".equals(on.getKeyProperty("virtualContext"));
            } catch (Exception e) {
                virtualContext = false;
            }
            if (virtualContext) {
                oForm = new WebAppVirtualCatalinaForm();
                oForm.reset(p_Mapping, p_Request);
                m_Session.setAttribute("webAppForm", oForm);
                m_Session.setAttribute("webAppVirtualCatalinaForm", oForm);
            } else {
                oForm = new WebAppCatalinaForm();
                oForm.reset(p_Mapping, p_Request);
                m_Session.setAttribute("webAppForm", oForm);
                m_Session.setAttribute("webAppCatalinaForm", oForm);
            }
        } else if (m_WhereAreYou.isJettyServer() == true) {
            oForm = new WebAppJettyForm();
            oForm.reset(p_Mapping, p_Request);
            m_Session.setAttribute("webAppForm", oForm);
            m_Session.setAttribute("webAppJettyForm", oForm);
        }
        return oForm;
    }

    /**
     * Create a new War form
     * @param p_Mapping Mapping to reset form
     * @param p_Request Http request used
     * @return The new form or null if web server unknown
     */
    protected WarForm createWarForm(final ActionMapping p_Mapping, final HttpServletRequest p_Request) {
        WarForm oForm = new WarForm();
        oForm.reset(p_Mapping, p_Request);
        m_Session.setAttribute("warForm", oForm);
        return oForm;
    }

    /**
     * Populate a WebApp form in function of Web Server.
     * @param p_ObjectName The MBean name
     * @param p_Form The form to populate
     * @throws Exception
     */
    protected void populateWebApp(final String p_ObjectName, final WebAppForm p_Form) throws Exception {
        if (m_WhereAreYou.isCatalinaServer() == true) {
            if (p_Form instanceof WebAppVirtualCatalinaForm) {
                populateWebAppVirtualCatalina(p_ObjectName, (WebAppVirtualCatalinaForm) p_Form);
            } else {
                populateWebAppCatalina(p_ObjectName, (WebAppCatalinaForm) p_Form);
            }
        } else if (m_WhereAreYou.isJettyServer() == true) {
            populateWebAppJetty(p_ObjectName, (WebAppJettyForm) p_Form);
        }
    }

    /**
     * Populate a form with the Catalina Context MBean and with the JOnAS War
     * MBean if it's found.
     * @param p_ObjectName The MBean name
     * @param p_Form The form to populate
     * @throws Exception
     */
    protected void populateWebAppCatalina(final String p_ObjectName, final WebAppCatalinaForm p_Form) throws Exception {
        // Context
        ObjectName on = new ObjectName(p_ObjectName);
        p_Form.setObjectName(on.toString());
        p_Form.setName(on.getKeyProperty("name"));
        p_Form.setJ2eeApplication(on.getKeyProperty("J2EEApplication"));
        p_Form.setJ2eeServer(on.getKeyProperty("J2EEServer"));
        p_Form.setPathContext(WebAppItem.extractPathContext(p_Form.getName()));
        p_Form.setLabelPathContext(WebAppItem.extractLabelPathContext(p_Form.getPathContext(), m_WhereAreYou
                .getCurrentCatalinaDefaultHostName()));
        p_Form.setHost(getStringAttribute(on, "hostname"));
        p_Form.setCookies(getBooleanAttribute(on, "cookies"));
        p_Form.setReloadable(getBooleanAttribute(on, "reloadable"));
        p_Form.setSwallowOutput(getBooleanAttribute(on, "swallowOutput"));
        p_Form.setCrossContext(getBooleanAttribute(on, "crossContext"));
        p_Form.setOverride(getBooleanAttribute(on, "override"));
        p_Form.setState(getIntegerAttribute(on, "state"));
    }

    /**
     * Populate a form a virtual Catalina context.
     * @param p_ObjectName The MBean name
     * @param p_Form The form to populate
     * @throws Exception
     */
    protected void populateWebAppVirtualCatalina(final String p_ObjectName, final WebAppVirtualCatalinaForm p_Form)
            throws Exception {
        // Context
        ObjectName on = new ObjectName(p_ObjectName);
        ObjectName versioningService = new ObjectName(on.getDomain() + ":type=service,name=versioning");
        String pServer = m_WhereAreYou.getCurrentJonasServerName();
        Map<String, String> contexts = (Map<String, String>) JonasManagementRepr.getAttribute(on, "Contexts", pServer);
        String[] policies = (String[]) JonasManagementRepr.getAttribute(versioningService, "Policies", pServer);
        Map<String, Integer> nbSessions = new HashMap<String, Integer>(contexts.size());
        Map<String, String> objectNames = new HashMap<String, String>(contexts.size());
        Set<ObjectName> webModules = JonasManagementRepr.queryNames(new ObjectName("*:j2eeType=WebModule,*"), pServer);
        for (String context : contexts.keySet()) {
            Set<ObjectName> contextsON = JonasManagementRepr.queryNames(
                    new ObjectName("*:type=Manager,path=" + context + ",*"), pServer);
            // Use contextsON.iterator().next() since there's only one Manager
            // per path
            Integer activeSessions = (Integer) JonasManagementRepr.getAttribute(contextsON.iterator().next(), "activeSessions",
                    pServer);
            nbSessions.put(context, activeSessions);
            for (ObjectName webModule : webModules) {
                if (webModule.getKeyProperty("name").endsWith(context)) {
                    objectNames.put(context, webModule.toString());
                }
            }
        }

        p_Form.setObjectName(on.toString());
        p_Form.setName(on.getKeyProperty("name"));
        p_Form.setJ2eeApplication(on.getKeyProperty("J2EEApplication"));
        p_Form.setJ2eeServer(on.getKeyProperty("J2EEServer"));
        p_Form.setPathContext(WebAppItem.extractPathContext(p_Form.getName()));
        p_Form.setLabelPathContext(WebAppItem.extractLabelPathContext(p_Form.getPathContext(), m_WhereAreYou
                .getCurrentCatalinaDefaultHostName()));
        p_Form.setContexts(contexts);
        p_Form.setPolicies(policies);
        p_Form.setNbSessions(nbSessions);
        p_Form.setObjectNames(objectNames);
    }

    /**
     * Populate a form with the Jetty Context MBean
     * @param p_ObjectName Jetty WebContainer+WebApplicationContext MBean
     * @param p_Form The form to populate
     * @throws Exception
     */
    protected void populateWebAppJetty(final String p_ObjectName, final WebAppJettyForm p_Form) throws Exception {
        ObjectName on = new ObjectName(p_ObjectName);
        // Context
        p_Form.setStarted(getBooleanAttribute(on, "started"));
        p_Form.setResourceBase(getStringAttribute(on, "resourceBase"));
        p_Form.setDisplayName(getStringAttribute(on, "displayName"));
        p_Form.setPathContext(getStringAttribute(on, "contextPath"));
        p_Form.setLabelPathContext(WebAppItem.extractLabelPathContext(p_Form.getPathContext(), null));
    }

    /**
     * Return the JOnAS MBean War.
     * @param p_PathContext The path context to find
     * @return The JOnAS MBean War or null if not found
     * @throws Exception
     */
    protected ObjectName findJonasMbeanWar(final String p_PathContext, final String domainName, final String jonasServerName)
            throws Exception {
        ObjectName onRet = null;
        ObjectName on;
        String sPathContext;
        StringBuffer sb;

        Iterator itOnWars = JonasAdminJmx.getListMbean(JonasObjectName.allWars(domainName), jonasServerName).iterator();
        while (itOnWars.hasNext()) {
            on = (ObjectName) itOnWars.next();
            sPathContext = getStringAttribute(on, "ContextRoot");
            if (sPathContext.charAt(0) != '/') {
                sb = new StringBuffer("/");
                sb.append(sPathContext);
                sPathContext = sb.toString();
            }
            // Detect the good War
            if (p_PathContext.equals(sPathContext) == true) {
                onRet = on;
                break;
            }
        }
        return onRet;
    }

    /**
     * Return the WebApp MBean.
     * @param p_PathContext The path context to find
     * @return The WebApplication (WebModule) MBean or null if not found
     * @throws Exception
     */
    protected ObjectName findWebAppMbean(final String p_PathContext, final String jonasServerName) throws Exception {
        ObjectName onRet = null;
        if (m_WhereAreYou.isCatalinaServer() == true) {
            onRet = findJ2eeWebModuleMbean(p_PathContext, jonasServerName);
        } else if (m_WhereAreYou.isJettyServer() == true) {

        }
        return onRet;
    }

    /**
     * Return the J2ee WebModule MBean.
     * @param p_PathContext The path context to find
     * @return The WebApplication (WebModule) MBean or null if not found
     * @throws Exception
     */
    protected ObjectName findJ2eeWebModuleMbean(final String p_PathContext, final String jonasServerName) throws Exception {
        ObjectName onRet = null;
        ObjectName on;
        String sPathContext;
        String sSearchPathContext = p_PathContext;
        if (sSearchPathContext.charAt(0) != '/') {
            sSearchPathContext = "/" + p_PathContext;
        }

        Iterator itOns = JonasAdminJmx.getListMbean(J2eeObjectName.getWebModules(m_WhereAreYou.getCurrentCatalinaDomainName()),
                jonasServerName).iterator();
        while (itOns.hasNext()) {
            on = (ObjectName) itOns.next();
            // ori: sPathContext = getStringAttribute(on, "name");
            sPathContext = on.getKeyProperty("name");
            // Detect the good War
            if (sSearchPathContext.equals(sPathContext) == true) {
                onRet = on;
                break;
            }
        }
        return onRet;
    }

    /**
     * Populate a form with the JOnAS WebModule MBean given.
     * @param p_ObjectName The JOnAS WebModue MBean
     * @param p_Form The form to populate
     * @throws Exception
     */
    protected void populateWar(final ObjectName p_ObjectName, final WarForm p_Form, final String jonasServerName)
            throws Exception {
        if (p_ObjectName != null) {
            // p_Form.setPath(p_ObjectName.getKeyProperty("fname"));
            String webModulePath = null;
            URL webModulePathUrl = (URL) JonasManagementRepr.getAttribute(p_ObjectName, "warURL", jonasServerName);
            if (webModulePathUrl != null) {
                webModulePath = webModulePathUrl.toString();
            }
            p_Form.setPath(webModulePath);
            p_Form.setFilename(JonasAdminJmx.extractFilename(p_Form.getPath()));
            // here the hostName is set to null as the War MBean has
            // HostName=null
            // hope Jetty MBean will provide in the future the correct host name
            p_Form.setHostName(getStringAttribute(p_ObjectName, "hostname"));
            p_Form.setInEar(getBooleanAttribute(p_ObjectName, "inEarCase"));
            // p_Form.setContextRoot(getStringAttribute(p_ObjectName,
            // "ContextRoot"));
            p_Form.setContextRoot(getStringAttribute(p_ObjectName, "path"));
            p_Form.setJava2DelegationModel(getBooleanAttribute(p_ObjectName, "java2DelegationModel"));
            p_Form.setXmlContent(getStringAttribute(p_ObjectName, "deploymentDescriptor"));
            p_Form.setJonasXmlContent(getStringAttribute(p_ObjectName, "jonasDeploymentDescriptor"));
            p_Form.setServletsName((String[]) JonasManagementRepr.getAttribute(p_ObjectName, "servlets", jonasServerName));
            p_Form.setWarPath((URL) JonasManagementRepr.getAttribute(p_ObjectName, "warURL", jonasServerName));
            p_Form.setEarPath((URL) JonasManagementRepr.getAttribute(p_ObjectName, "earURL", jonasServerName));
            p_Form.setEarON((String) JonasManagementRepr.getAttribute(p_ObjectName, "earON", jonasServerName));
        }
    }

    /**
     * Populate a form with the JOnAS WebModule MBean given.
     * @param p_ObjectName The JOnAS WebModue MBean
     * @param p_Form The form to populate
     * @throws Exception
     */
    protected void populateJettyWar(final ObjectName p_ObjectName, final WarForm p_Form, final String jonasServerName)
            throws Exception {
        if (p_ObjectName != null) {
            p_Form.setPath(p_ObjectName.getKeyProperty("fname"));
            p_Form.setFilename(JonasAdminJmx.extractFilename(p_Form.getPath()));

            p_Form.setHostName(getStringAttribute(p_ObjectName, "HostName"));
            p_Form.setInEar(getBooleanAttribute(p_ObjectName, "InEarCase"));
            p_Form.setContextRoot(getStringAttribute(p_ObjectName, "ContextRoot"));
            p_Form.setJava2DelegationModel(getBooleanAttribute(p_ObjectName, "Java2DelegationModel"));
            p_Form.setXmlContent(getStringAttribute(p_ObjectName, "XmlContent"));
            p_Form.setJonasXmlContent(getStringAttribute(p_ObjectName, "JOnASXmlContent"));
            p_Form.setServletsName((String[]) JonasManagementRepr.getAttribute(p_ObjectName, "ServletsName", jonasServerName));
            p_Form.setWarPath((URL) JonasManagementRepr.getAttribute(p_ObjectName, "WarURL", jonasServerName));
            p_Form.setEarPath((URL) JonasManagementRepr.getAttribute(p_ObjectName, "EarURL", jonasServerName));
        }
    }

    /**
     * Populate a form with the JOnAS War path given.
     * @param p_Path The JOnAS War MBean path
     * @param p_Form The form to populate
     * @throws Exception
     */
    protected void populateWar(final String p_Path, final WarForm p_Form, final String domainName, final String jonasServerName)
            throws Exception {
        populateWar(JonasObjectName.war(domainName, p_Path), p_Form, jonasServerName);
    }
}
