/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2007 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;

import java.io.UnsupportedEncodingException;
import java.util.Hashtable;

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

import org.apache.struts.action.ActionServlet;
import org.ow2.jonas.lib.bootstrap.JProp;
import org.ow2.jonas.lib.management.extensions.base.AdminException;
import org.ow2.jonas.lib.management.extensions.base.AdminHelper;
import org.ow2.jonas.lib.management.extensions.base.AdminJmxHelper;
import org.ow2.jonas.lib.management.extensions.base.JonasManagementRepr;
import org.ow2.jonas.lib.management.extensions.base.mbean.CatalinaObjectName;
import org.ow2.jonas.lib.management.javaee.J2eeObjectName;
import org.ow2.jonas.lib.util.ConfigurationConstants;
import org.ow2.jonas.management.extensions.base.api.ManagementException;
import org.ow2.jonas.webapp.taglib.TreeControl;
import org.ow2.jonas.webapp.taglib.TreeControlNode;

/**
 * @author Michel-Ange ANTON
 */
/**
 * @author eyindanga
 */
public class WhereAreYou extends AdminHelper {


    /**
     * Name of the variable in http session
     */
    public final static String SESSION_NAME = "WhereAreYou";

    // Constant environnement
    public final static String TAGS_IMAGES_ROOT_KEY = "tagsimagesroot";
    public final static String CONTEXT_MACRO = "${CONTEXT}";
    public final static String TREE_PAGE_REFRESH = "viewTree.do?select=";
    public final static String EXCEPTION_JONASSERVER_NOTFOUND = "error.jonasserver.notfound";
    /**
     * Used separator in the ident node in the tree
     */
    public final static String NODE_SEPARATOR = "*";

    /**
     * Node name separator.
     */
    public final static String NODE_NAME_SEPARATOR = "/";

    /**
     * Node name separator.
     */
    public final static String J2EE_APPLICATION_KEY = "J2EEApplication";

//	--------------------------------------------------------- Properties variable

    private String imagesRoot = null;
    private TreeControl treeControl = null;
    private boolean treeToRefresh = false;



//	--------------------------------------------------------- Constructor

    public WhereAreYou() {
        super();
        try {
            // Get the name of the Jonas Server who is running the application
            JProp oJProp = JProp.getInstance();
            adminJonasServerName = oJProp.getValue(ConfigurationConstants.JONAS_NAME_PROP);
            adminJonasServerConfDir = oJProp.getConfDir();
            currentDomainName = oJProp.getValue(ConfigurationConstants.DOMAIN_NAME_PROP);
            currentDomain = J2eeObjectName.J2EEDomain(currentDomainName);
            currentJonasServerName = adminJonasServerName;
            currentJonasServer = J2eeObjectName.J2EEServer(currentDomainName, currentJonasServerName);
            clusterdGraphAttributes = new Hashtable();
            configuredServerForClusterDaemonList = new Hashtable();
            removedServersPerClusterd = new Hashtable();
        } catch (Exception e) {
            // Current Jonas not found, can't run jonasAdmin
            throw new JonasAdminException(EXCEPTION_JONASSERVER_NOTFOUND, e.getMessage(), e);
        }
    }

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

    /**
     * Initialize the properties in only reading.
     *
     * @param p_Servlet The instance of servlet to access to the parameter of the servlet config
     * @param p_Request The request to access to the HTTP informations
     * @throws JonasAdminException
     */
    public void initialize(final ActionServlet p_Servlet, final HttpServletRequest p_Request)
    throws JonasAdminException {
        // Tags Images Root directory
        String sImagesRoot = p_Servlet.getServletConfig().getInitParameter(
                TAGS_IMAGES_ROOT_KEY);
        if (sImagesRoot != null) {
            sImagesRoot = JonasAdminJmx.replace(sImagesRoot, CONTEXT_MACRO
                    , p_Request.getContextPath());
        }
        this.imagesRoot = sImagesRoot;
        refreshServers(p_Request, currentDomainName, currentJonasServerName);
    }
    /**
     * Return the name of the selected node in the tree.
     *
     * @return The name
     */
    public String getSelectedNameNode() {
        if (treeControl != null) {
            TreeControlNode oNode = treeControl.getSelected();
            if (oNode != null) {
                return oNode.getName();
            }
        }
        return null;
    }

    /**
     * Return the URL to refresh the selected node in the tree.
     *
     * @param p_Request HTTP request
     * @param p_Response HTTP response
     * @return The URL
     */
    public String getUrlToRefreshSelectedNode(final HttpServletRequest p_Request
            , final HttpServletResponse p_Response) {
        if (treeControl != null) {
            TreeControlNode oNode = treeControl.getSelected();
            if (oNode != null) {
                // Disable refresh
                treeToRefresh = false;
                // Build URL refresh
                String encodedName = null;
                try {
                    encodedName = java.net.URLEncoder.encode(oNode.getName(), "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    // Node name can't be encoded
                    encodedName = oNode.getName();
                }
                StringBuffer sb = new StringBuffer();
                sb.append(p_Request.getContextPath());
                sb.append("/");
                sb.append(TREE_PAGE_REFRESH);
                sb.append(encodedName);
                // Force the browser to refresh the tree (Netscape and Mozilla)
                sb.append("&s=");
                sb.append(Math.random());

                return p_Response.encodeURL(sb.toString());
            }
        }
        return null;
    }

    /**
     * Select the node in the tree.
     *
     * @param p_Name The name of node to select
     * @param p_Expand Expand parent branch
     */
    public void selectNameNode(final String p_Name, final boolean p_Expand) {
        if (treeControl != null) {
            // Changing node ?
            if (p_Name.equals(getSelectedNameNode()) == false) {
                // Change node
                treeControl.selectNode(p_Name);
                if (p_Expand == true) {
                    treeControl.expandSelectedParents();
                }
                treeToRefresh = true;
            }
            // Query node not found
            if ((getSelectedTreeControlNode() == null) && (p_Name != null) && (p_Name.length() > 0)) {
                // Try to select the parent node
                String s = p_Name.substring(0, p_Name.lastIndexOf(WhereAreYou.NODE_SEPARATOR));
                if ((s != null) && (s.length() > 0)) {
                    selectNameNode(s, p_Expand);
                }
            }
        }
    }

    /**
     * Return the selected node in the tree.
     *
     * @return The selected node
     */
    public TreeControlNode getSelectedTreeControlNode() {
        if (treeControl != null) {
            return treeControl.getSelected();
        }
        return null;
    }

    /**
     * Return the state of current display of tree.
     *
     * @return True if the current tree is not correctly displaying
     */
    public boolean isTreeToRefresh() {
        return treeToRefresh;
    }

    /**
     * Change the state of current display of tree.
     *
     * @param treeToRefresh True to refresh
     */
    public void setTreeToRefresh(final boolean treeToRefresh) {
        this.treeToRefresh = treeToRefresh;
    }

  //------------------------------------------- refresh operations.
      /**
       * Refresh all the servers properties.
       *
       * @param p_Request The request to access to the HTTP informations
       * @throws ManagementException if could not connect to the MBeanServer
       * @throws AdminException
       */
      public void refreshServers(final HttpServletRequest p_Request, final String domainName, final String serverName)
      throws ManagementException, AdminException {
          refreshJonas(p_Request, serverName);
          applicationServerPort = p_Request.getServerPort();
          applicationContextPath = p_Request.getContextPath();
          refreshCatalina(p_Request, domainName);
          refreshJetty(p_Request, domainName);
      }
      public void refreshServers(final HttpServletRequest p_Request) {
          // Nothing to do, no server change
      }
      /**
       * Refresh the Catalina server properties.
       *
       * @param p_Request The request to access to the HTTP informations
       */
      public void refreshCatalina(final HttpServletRequest p_Request, final String domainName) {
          resetCatalina();
          try {
              String servletServerName = getServletServerName(domainName);
              if (servletServerName == null) {
                  return;
              }
              String sServer = servletServerName.toLowerCase();
              catalinaServer = (sServer.indexOf("tomcat") > -1);
              if (catalinaServer) {
                  ObjectName onServer = AdminJmxHelper.getFirstMbean(CatalinaObjectName.catalinaServer(), currentJonasServerName);
                  ObjectName[] aonServices = (ObjectName[]) JonasManagementRepr.getAttribute(onServer
                          , "serviceNames", currentJonasServerName);
                  // Service : the first !
                  currentCatalinaServiceName = aonServices[0].getKeyProperty("serviceName");
                  // Domain
                  currentCatalinaDomainName = aonServices[0].getDomain();
                  // Engine
                  currentCatalinaEngineName = currentCatalinaDomainName;
                  ObjectName onEngine = CatalinaObjectName.catalinaEngine(currentCatalinaDomainName);
                  // Default Host
                  currentCatalinaDefaultHostName = (String) JonasManagementRepr.getAttribute(onEngine
                          , "defaultHost", currentJonasServerName);
              }
          } catch (Exception e) {
              // none
          }
      }

      /**
       * Refresh the Jetty server properties.
       *
       * @param p_Request The request to access to the HTTP informations
       */
      public void refreshJetty(final HttpServletRequest p_Request, final String domainName) {
          resetJetty();
          try {
              String servletServerName = getServletServerName(domainName);
              if (servletServerName == null) {
                  return;
              }
              String sServer = servletServerName.toLowerCase();
              jettyServer = (sServer.indexOf("jetty") > -1);
              if (jettyServer == true) {
                  // none action
              }
          }
          catch (Exception e) {
              // none
          }
      }

      /**
       * Refresh the managed JOnAS server properties.
       *
       * @param p_Request The request to access to the HTTP informations
       * @throws ManagementException if could not connect to the MBeanServer
       * @throws AdminException
       */
      public void refreshJonas(final HttpServletRequest p_Request, final String serverName)
      throws ManagementException, AdminException {
          resetJonas();
          // Set J2EEServer information
          currentJonasServerName = serverName;
          currentJonasServer = J2eeObjectName.J2EEServer(currentDomainName, serverName);

          // Detect if the current managed JOnAS server is the one where the application is running
          theCurrentJonasServer = adminJonasServerName.equals(currentJonasServerName);

      }

    /**
     * Return in a string the contents of the instance for each propertie.
     * Debug utility.
     *
     * @return The string contents
     */
    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("imagesRoot=[").append(imagesRoot).append("] ");
        sb.append("treeControl=[").append(treeControl).append("] ");
        sb.append("catalinaServer=[").append(catalinaServer).append("] ");
        return sb.toString();
    }

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



//	--------------------------------------------------------- Properties Methods

    public String getImagesRoot() {
        return imagesRoot;
    }

    public TreeControl getTreeControl() {
        return treeControl;
    }

    public void setTreeControl(final TreeControl treeControl) {
        this.treeControl = treeControl;
    }
}
