/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2007-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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id: ApplyCmiAction.java 17531 2009-06-04 13:02:14Z eyindanga $
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.webapp.jonasadmin.cmi;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.domain.DomainMonitor;
import org.ow2.jonas.lib.management.domain.J2EEDomain;
import org.ow2.jonas.lib.management.extensions.base.JonasManagementRepr;
import org.ow2.jonas.lib.util.JonasObjectName;
import org.ow2.jonas.webapp.jonasadmin.JonasAdminJmx;
import org.ow2.jonas.webapp.jonasadmin.JonasBaseAction;
import org.ow2.jonas.webapp.jonasadmin.WhereAreYou;
/**
 * This class executes CMI Actions.
 * @author eyindanga
 *
 */
public class ApplyCmiAction extends JonasBaseAction {

    @SuppressWarnings("unchecked")
    @Override
    public ActionForward executeAction(final ActionMapping p_Mapping, final ActionForm p_Form, final HttpServletRequest p_Request, final HttpServletResponse p_Response) throws IOException, ServletException {
        String sDomainName = m_WhereAreYou.getCurrentDomainName();
        String serverName = m_WhereAreYou.getCurrentJonasServerName();

        // Force the node selected in tree
        m_WhereAreYou.selectNameNode("domain"
                + WhereAreYou.NODE_SEPARATOR
                + serverName, true);

        CmiForm oForm = (CmiForm) p_Form;
        String forwardName = "displayCmiInfo";
        String action = oForm.getAction();
        if (m_Session.getAttribute("currentCmiCluster") != null) {
            //free session var to let the garbage clean it.
             m_Session.setAttribute("currentCmiCluster", null);
        }
        //The style of the html text containing delay to refresh. This style will be different if the delay is changed by user
        p_Request.setAttribute("htmlTextStyle", "htmlText");
        try {
            ObjectName cmiOn = JonasObjectName.cmiServer(sDomainName, serverName);
            if (JonasAdminJmx.hasMBeanName(cmiOn, serverName)) {
                if (action != null) {
                    if (action.equals("refresh")) {
                        JonasManagementRepr.setAttribute(cmiOn, "DelayToRefresh", new Integer(oForm.getDelayToRefresh()), serverName);
                        //Set the style of html text containing new delay to refresh.
                        p_Request.setAttribute("htmlTextStyle", "htmlTextChanged");
                        // unset action
                        oForm.setAction(null);
                    }else if("blacklist".equals(oForm.getAction())) {
                        /**
                         * Blacklist the server
                         */
                        String[] signature = {"java.lang.String"};
                        String[] params = {oForm.getServerUrl()};
                        JonasManagementRepr.invoke(cmiOn, "addServerToBlackList", params, signature, serverName);
                    }else if ("unblacklist".equals(oForm.getAction())) {
                        /**
                         * Unblacklist the server
                         */
                        String[] signature = {"java.lang.String"};
                        String[] params = {oForm.getServerUrl()};
                        JonasManagementRepr.invoke(cmiOn, "removeServerFromBlackList", params, signature, serverName);
                        //Enable or disable current cmi server
                    }
                }
                Set clusterList = (Set)JonasManagementRepr.getAttribute(cmiOn, "ClusterNames", serverName);
                List<ClusterAttribute> cmiClusterList = new ArrayList();
                for (Iterator iter = clusterList.iterator(); iter.hasNext();) {
                    String[] signature = {"java.lang.String"};
                    String clusterName = (String) iter.next();
                    String[] params = {clusterName};
                    Set objectList = (Set)JonasManagementRepr.invoke(cmiOn, "getObjectNames", params, signature, serverName);
                    cmiClusterList.add(new ClusterAttribute(clusterName, objectList));
                }
                oForm.setCmiClusterList(cmiClusterList);
                oForm.getProtocols().clear();
                //getting all server proxies of the domain.
                DomainMonitor dm = J2EEDomain.getInstance().getDomainMonitor();
                Collection serverList = null;
                if (dm.isMaster()) {
                    serverList = dm.getServerList();
                }

                Iterator itNames = ((Set<String>)JonasManagementRepr.getAttribute(cmiOn, "Protocols", serverName)).iterator();
                while (itNames.hasNext()) {
                    Protocol proto = new Protocol();
                    String protocol  = (String) itNames.next();
                    String[] params = {protocol};
                    String[] sign = {"java.lang.String"};
                    /**
                     * Get provider URLs for each protocol
                     */
                    Set<String> providerUrls =(Set<String>)JonasManagementRepr.invoke(cmiOn, "getServerRefsForProtocol", params, sign, serverName);
                    for (Iterator iterator = providerUrls.iterator(); iterator
                            .hasNext();) {

                        String providerUrl = (String) iterator.next();
                        Provider prov = new Provider();
                        String[] parameters = {providerUrl, protocol};
                        String[] signature = {"java.lang.String", "java.lang.String"};
                        Set objectList = (Set)JonasManagementRepr.invoke(cmiOn, "getServerObjectsForProtocol", parameters, signature, serverName);
                        prov.setUrl(providerUrl);
                        prov.setName("");
                        if (serverList != null) {
                             prov.setName(JonasBaseAction.getNameForProvider(providerUrl, serverList));
                        }


                        String[] signat = {"java.lang.String"};
                        String[] par = {providerUrl};
                        prov.setIsBlackListed((Boolean)JonasManagementRepr.invoke(cmiOn, "isServerBlackListed", par, signat, serverName));
                        prov.setListNames(objectList);
                        proto.getProviders().add(prov);
                    }
                    proto.setName(protocol);
                    oForm.getProtocols().add(proto);
                    m_Session.setAttribute("currentCmiForm", oForm);
                }
                //get availaible LBPolicies
                Map<String, Set<String>> availablePoliciesAndStrategies =
                    (Map<String, Set<String>>) JonasManagementRepr.invoke(
                            cmiOn, "retrieveAvailablePoliciesAndStrategies", null, null, serverName);
                oForm.setAvailableLBPolicies(getLBClasses(availablePoliciesAndStrategies, "policies"));
                oForm.setAvailableLBStrategies(getLBClasses(availablePoliciesAndStrategies, "strategies"));
                oForm.setDelayToRefresh(((Integer)JonasManagementRepr.getAttribute(cmiOn, "DelayToRefresh", serverName)).intValue());
            }else {
                //cmi mbean is not registered
                p_Request.setAttribute("newcmi", false);
            }

        }catch (Throwable t) {
            addGlobalError(t);
            saveErrors(p_Request, m_Errors);
            return (p_Mapping.findForward("Global Error"));
        }
        // Forward to the jsp.
        return (p_Mapping.findForward(forwardName));
    }

    /**
     * Build a Hashmap of full class names/simple class name that will be displayed in a html select
     * @param availableLBPoliciesAndStrategies
     * @param lbType
     * @return
     */
    private HashMap<String, String> getLBClasses(
            final Map<String, Set<String>> availableLBPoliciesAndStrategies,
            final String lbType) {
        HashMap<String, String> ret = new HashMap<String, String>();
        Set<String> fullClassNames =  availableLBPoliciesAndStrategies.get(lbType);
        for (Iterator<String> iterator = fullClassNames.iterator(); iterator.hasNext();) {
            String fullClassName = iterator.next();
            ret.put(fullClassName, getSimpleClassName(fullClassName));
        }

        return ret;
    }

    /**
     * get simple class name from a full class name. e.g org.toto.Titi --> Titi
     * @param fullClassName
     * @return
     */
    private String getSimpleClassName(final String fullClassName) {
        // TODO Auto-generated method stub
        for (int i = fullClassName.length() - 1; i >= 0; i--) {
            if (String.valueOf(fullClassName.charAt(i)).equals(".")) {
                return fullClassName.substring(i + 1, fullClassName.length());
            }
        }
        return fullClassName;
    }
}
