Package com.sun.enterprise.ee.admin.configbeans

Source Code of com.sun.enterprise.ee.admin.configbeans.ServersConfigBean$GetRuntimeStatusTask

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package com.sun.enterprise.ee.admin.configbeans;

import com.sun.enterprise.ee.admin.PortInUseException;
import com.sun.enterprise.ee.admin.PortInUse;
import com.sun.enterprise.ee.admin.PortReplacedException;

import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.SystemProperty;
import com.sun.enterprise.config.serverbeans.NodeAgents;
import com.sun.enterprise.config.serverbeans.NodeAgent;
import com.sun.enterprise.config.serverbeans.Configs;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.Applications;
import com.sun.enterprise.config.serverbeans.ConnectorModule;
import com.sun.enterprise.config.serverbeans.EjbModule;
import com.sun.enterprise.config.serverbeans.J2eeApplication;
import com.sun.enterprise.config.serverbeans.WebModule;
import com.sun.enterprise.config.serverbeans.Resources;
import com.sun.enterprise.config.serverbeans.ConnectorResource;
import com.sun.enterprise.config.serverbeans.JdbcResource;
import com.sun.enterprise.config.serverbeans.Servers;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.ApplicationRef;
import com.sun.enterprise.config.serverbeans.ResourceRef;
import com.sun.enterprise.config.serverbeans.ServerRef;
import com.sun.enterprise.config.serverbeans.Cluster;
import com.sun.enterprise.config.serverbeans.ConfigAPIHelper;
import com.sun.enterprise.config.serverbeans.ServerHelper;
import com.sun.enterprise.config.serverbeans.ClusterHelper;
import com.sun.enterprise.config.serverbeans.NodeAgentHelper;
import com.sun.enterprise.config.serverbeans.ElementProperty;
import com.sun.enterprise.config.ConfigException;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.config.impl.ConfigContextImpl;

import com.sun.enterprise.admin.common.Status;
import com.sun.enterprise.admin.servermgmt.InstanceException;
import com.sun.enterprise.ee.admin.servermgmt.AgentException;
import com.sun.enterprise.admin.servermgmt.RuntimeStatus;
import com.sun.enterprise.admin.servermgmt.RuntimeStatusList;
import com.sun.enterprise.util.SystemPropertyConstants;
import com.sun.enterprise.util.i18n.StringManager;
import com.sun.enterprise.util.i18n.StringManagerBase;
import com.sun.enterprise.util.net.NetUtils;
import com.sun.enterprise.admin.target.TargetType;
import com.sun.enterprise.admin.target.Target;
import com.sun.enterprise.admin.target.TargetBuilder;
import com.sun.enterprise.admin.util.IAdminConstants;
import com.sun.enterprise.server.Constants;
import com.sun.enterprise.ee.admin.clientreg.InstanceRegistry;
import com.sun.enterprise.ee.admin.clientreg.NodeAgentRegistry;
import com.sun.enterprise.ee.admin.clientreg.MBeanServerConnectionInfo;

import com.sun.logging.ee.EELogDomains;

import com.sun.enterprise.ee.admin.servermgmt.EEInstancesManager;

import com.sun.enterprise.ee.admin.proxy.NodeAgentProxy;
import com.sun.enterprise.ee.admin.mbeanapi.NodeAgentMBean;

import com.sun.enterprise.ee.admin.proxy.InstanceProxy;
import com.sun.enterprise.ee.admin.mbeanapi.ServerRuntimeMBean; 

import com.sun.enterprise.ee.admin.concurrent.Task;
import com.sun.enterprise.ee.admin.concurrent.Executor;   

import com.sun.enterprise.addons.AddonFacade;
import java.rmi.RemoteException;

import java.util.logging.Logger;
import java.util.logging.Level;       
import java.util.Properties;
import java.util.Enumeration;
import java.util.ArrayList;
import java.io.File;
import javax.management.MBeanException;

//ISSUE: Do we really want to throws an InstanceException here as this will clients
//using this mbean to have our runtime; however we seem to be throwing our own
//exceptions everywhere else in the mbeans. The problem with MBeanException
//currently is that it masks the real exception (due to the fact that MBeanHelper
//does some bogus formatting on the exception.

public class ServersConfigBean extends ServersAndClustersBaseBean implements IAdminConstants
{   
   
    class GetRuntimeStatusTask extends Task {
        private static final long TIMEOUT_IN_MILLIS = 30000;
       
        private String _serverName;
        private RuntimeStatus _status;
       
        public GetRuntimeStatusTask(String serverName) {
            super(TIMEOUT_IN_MILLIS);
            _serverName = serverName;
            _status = new RuntimeStatus(_serverName);
        }
       
        public RuntimeStatus getStatus() {
            return _status;
        }
       
        public void run() {           
            try {
                _status = getRuntimeStatus(_serverName);
            } catch (InstanceException ex) {
                StringManagerBase sm = StringManagerBase.getStringManager(
                    getLogger().getResourceBundleName());        
                getLogger().log(Level.WARNING,
                    sm.getString("eeadmin.listInstances.Exception", _serverName), ex);
                _status = new RuntimeStatus(_serverName);
            }           
        }
    }        
   
    private static final StringManager _strMgr =
        StringManager.getManager(ServersConfigBean.class);
   
    private static final TargetType[] VALID_LIST_TYPES = new TargetType[] {
        TargetType.DOMAIN, TargetType.CLUSTER, TargetType.SERVER, TargetType.NODE_AGENT};
       
    private static final TargetType[] VALID_TYPES = new TargetType[] {
        TargetType.SERVER};       
       
    public ServersConfigBean(ConfigContext configContext) {
        super(configContext);       
    }
   
    public void clearRuntimeStatus(String serverName) throws InstanceException
    {       
        try {                        
            ServerRuntimeMBean serverMBean = InstanceProxy.getInstanceProxy(serverName);
            serverMBean.clearRuntimeStatus();
        } catch (Exception ex) {
            //Ignore any error indicating that the server is unreachable.
            //FIXTHIS: We could expect the proxy to do this for us as it
            //seems to be a common case.
            if (InstanceProxy.isUnreachable(ex)) {
                // do nothing
            } else {
                throw new InstanceException(ex);                       
            }
        }       
    }
     
    public RuntimeStatus getRuntimeStatus(String serverName) throws InstanceException
    {       
        try {                        
            ServerRuntimeMBean serverMBean = InstanceProxy.getInstanceProxy(serverName);
            return serverMBean.getRuntimeStatus();
        } catch (Exception ex) {
            //Ignore any error indicating that the server is unreachable.
            //FIXTHIS: We could expect the proxy to do this for us as it
            //seems to be a common case.
            if (InstanceProxy.isUnreachable(ex)) {
                return new RuntimeStatus(serverName);
            } else {
                throw new InstanceException(ex);                       
            }
        }
    }      
   
    public boolean isRunning(String serverName) throws InstanceException
    {
        return getRuntimeStatus(serverName).isRunning();
    }
   
    /**
     * Fetches the runtime status of the given server instances in parallel.
     */
    public RuntimeStatusList getRuntimeStatus(Server[] servers)
    {    
        return getRuntimeStatus(toStringArray(servers));
    }          
       
    public RuntimeStatusList getRuntimeStatus(String[] servers)
    {
        GetRuntimeStatusTask[] tasks = new GetRuntimeStatusTask[servers.length];
        for (int i = 0; i < servers.length; i++) {
            tasks[i] = new GetRuntimeStatusTask(servers[i]);
        }
        Executor exec = new Executor(tasks);
        exec.run();
        RuntimeStatusList result = new RuntimeStatusList(servers.length);
        for (int i = 0; i < servers.length; i++) {
            result.add(tasks[i].getStatus());
        }       
        return result;
    }   
   
    public RuntimeStatusList getServerInstanceRuntimeStatus(String targetName)
        throws InstanceException
    {
        final ConfigContext configContext = getConfigContext();
        final StringManager stringMgr = StringManager.getManager(EEInstancesManager.class);       
        try {                              
            final Target target = TargetBuilder.INSTANCE.createTarget(
                DOMAIN_TARGET, VALID_LIST_TYPES, targetName, configContext);                   
            final Server[] servers = target.getServers();                         
            return getRuntimeStatus(servers);                           
        } catch (Exception ex) {
            throw getExceptionHandler().handleInstanceException(
                ex, "eeadmin.listInstances.Exception", targetName);
        }        
    }
   
    /**
     * Lists server instances.
     */
    public String[] listServerInstancesAsString(
        String targetName, boolean andStatus) throws InstanceException
   {
        final ConfigContext configContext = getConfigContext();
        final StringManager stringMgr = StringManager.getManager(EEInstancesManager.class);       
        try {                              
            final Target target = TargetBuilder.INSTANCE.createTarget(
                DOMAIN_TARGET, VALID_LIST_TYPES, targetName, configContext);                   
            final Server[] servers = target.getServers();         
            final int numServers = servers.length;           
            ArrayList result = new ArrayList();
            String serverName = null;
            int status;           
            RuntimeStatusList statusList = null;
            if (andStatus) {               
                //Fetch the status of all the server instances in parallel
                statusList = getRuntimeStatus(servers);               
            }
            for (int i = 0; i < numServers; i++) {               
                serverName = servers[i].getName();
                if (andStatus) {
                    //Do not display the DAS as a server instance
                    if (!ServerHelper.isDAS(configContext, serverName)) {                                              
                        result.add(stringMgr.getString("listInstanceElement", serverName,
                            statusList.getStatus(i).toShortString()));                       
                    }
                } else {
                    result.add(serverName);
                }
            }           
            return (String[])result.toArray(new String[result.size()]);
        } catch (Exception ex) {
            throw getExceptionHandler().handleInstanceException(
                ex, "eeadmin.listInstances.Exception", targetName);
        }        
    }
   
    public String listDASServerInstanceAsString(boolean andStatus) throws InstanceException
    {
        final ConfigContext configContext = getConfigContext();
        String dasName = null;
        try {
            final Server das = ServerHelper.getDAS(configContext);
            dasName = das.getName();
            return listServerInstancesAsString(dasName, andStatus)[0];
        } catch (Exception ex) {
            throw getExceptionHandler().handleInstanceException(
                ex, "eeadmin.listInstances.Exception", dasName);
        }   
    }
  
       
    public String[] listUnclusteredServerInstancesAsString(
        boolean andStatus, boolean excludeDASInstance)
        throws InstanceException
    {
        final ConfigContext configContext = getConfigContext();
        final StringManager stringMgr = StringManager.getManager(EEInstancesManager.class);
        try {           
            final Server[] servers = ServerHelper.getUnclusteredServers(
                configContext, excludeDASInstance);           
            ArrayList result = new ArrayList();
            String serverName;
            RuntimeStatusList statusList = null;
            if (andStatus) {               
                //Fetch the status of all the server instances in parallel
                statusList = getRuntimeStatus(servers);               
            }
            for (int i = 0; i < servers.length; i++) {               
                serverName = servers[i].getName();
                if (andStatus) {                    
                    result.add(stringMgr.getString("listInstanceElement", serverName,
                        statusList.getStatus(i).toShortString()));                   
                } else {
                    result.add(serverName);
                }               
            }
            return (String[])result.toArray(new String[result.size()]);
        } catch (Exception ex) {
            throw getExceptionHandler().handleInstanceException(
                ex, "eeadmin.listInstances.Exception", "unclustered instances");
        }       
    }
   
    /**
     * Starts the specified server instance. This operation is invoked by the asadmin start-instance
     * command.
     */
    public void startServerInstance(String serverName) throws InstanceException
    {
        startServerInstance(serverName, null);
    }
   
    /**
     * Starts the specified server instance. This operation is invoked by the asadmin start-instance
     * when invoked with setenv option.
     */
    public void startServerInstance(
        String serverName, Properties props) throws InstanceException
    {
        try {
            final ConfigContext configContext = getConfigContext();
            //validate that the server exists and return its node agent
            Target target = null;
            try {
                target = TargetBuilder.INSTANCE.createTarget(
                    VALID_TYPES, serverName, configContext);  
            } catch (Exception e) {
                throw new InstanceException(
                    _strMgr.getString("noSuchInstance", serverName));
            }
            NodeAgent controller = target.getNodeAgents()[0];
            String agentName = controller.getName();
                                   
            // Call the Node Agent to start the server instance remotely
            NodeAgentsConfigBean ncb = getNodeAgentsConfigBean();
            if (ncb.isRunning(agentName)) {
                if (isRunning(serverName)) {
                    // WBN January 2007 Issue 726
                    // This is now OFFICIALLY not an error.  Log it and return
                    StringManagerBase sm = StringManagerBase.getStringManager(
                        getLogger().getResourceBundleName());        
                    getLogger().log(Level.WARNING,
                        sm.getString("eeadmin.already.running", serverName));
                    return;
                } else {
                    String installRoot = System.getProperty(
                    SystemPropertyConstants.INSTALL_ROOT_PROPERTY);
                    String instanceRoot = System.getProperty(
                    SystemPropertyConstants.INSTANCE_ROOT_PROPERTY);
                    NodeAgentMBean agentMBean = NodeAgentProxy.getNodeAgentProxy(agentName);                       
                    agentMBean.startInstance(serverName, props);       
                }
            } else {
                throw new InstanceException(_strMgr.getString("agentNotRunning",
                    agentName, serverName));
            }
        } catch (Exception ex) {
            throw getExceptionHandler().handleInstanceException(
                ex, "eeadmin.startServerInstance.Exception", serverName);
        }
    }
   
    /**
     * Stops the specified server instance. This operation is invoked by the asadmin stop-instance
     * command.
     */
    public void stopServerInstance(
        String serverName, int timeout) throws InstanceException
    {
        stopServerInstance(serverName, true, timeout);
    }
   
    /**
     * Stops the specified server instance. This operation is invoked by the asadmin stop-instance
     * command.
     */
    public void stopServerInstance(
        String serverName) throws InstanceException
    {
        stopServerInstance(serverName, false, -1);
    }
   
    /**
     * Stops the specified server instance. This operation is invoked by the asadmin stop-instance
     * command.
     */
    private void stopServerInstance(
        String serverName, boolean forcekill, int timeout) throws InstanceException
    {
        try {
            final ConfigContext configContext = getConfigContext();
            //validate that the server exists and return its node agent
            final Target target = TargetBuilder.INSTANCE.createTarget(
                VALID_TYPES, serverName, configContext);  
            NodeAgent controller = target.getNodeAgents()[0];
            String agentName = controller.getName();
                      
            // Call the Node Agent to stop the server instance remotely
            NodeAgentsConfigBean ncb = getNodeAgentsConfigBean();
            if (ncb.isRunning(agentName)) {
                    NodeAgentMBean agentMBean =
                        NodeAgentProxy.getNodeAgentProxy(agentName);
                    if (forcekill) {
                        agentMBean.stopInstance(serverName, timeout);
                    } else {
                        agentMBean.stopInstance(serverName);
                    }
            } else throw new InstanceException(
                   _strMgr.getString("agentNotRunning", agentName, serverName));           
        } catch (Exception ex) {
            throw getExceptionHandler().handleInstanceException(
                ex, "eeadmin.stopServerInstance.Exception", serverName);           
        }
    }
   
    /**
     * Restart server instance
     */
    public void restartServerInstance(
        String serverName) throws InstanceException
    {
  boolean restarted = false;

  try {

      // stop the instance only if it is running
      if (isRunning(serverName)) {
    stopServerInstance(serverName);
      }

      // start the instance only if it is stopped
      if (! isRunning(serverName)) {
    startServerInstance(serverName, null);
    restarted = true;
      }

      // if none of the above are true then the restart is a failure
      // throw appropriate exception
      if (! restarted) {
                throw new InstanceException(_strMgr.getString("serverCannotRestart",
      serverName));
      }

        } catch (Exception ex) {
            throw getExceptionHandler().handleInstanceException(
                ex, "eeadmin.restartServerInstance.Exception", serverName);
        }
    }

   
    private void deleteClusterReferences(String serverName)
        throws ConfigException, InstanceException
    {
        //If the instance is clustered, the we must remove the server refs from
        //the cluster.
        final ConfigContext configContext = getConfigContext();
        final Cluster cluster = ClusterHelper.getClusterForInstance(configContext, serverName);
        final ServerRef ref = cluster.getServerRefByRef(serverName);
        if (ref == null) {
            throw new InstanceException(_strMgr.getString("clusterMissingServerRef",
                cluster.getName(), serverName));
        } else {
            cluster.removeServerRef(ref, OVERWRITE);
        }
    }
   
    /**
     * Deletes the specified server instance. This operation is invoked by the asadmin delete-instance
     * command.
     */   
    public void deleteServerInstance(String serverName) throws InstanceException
    {
        try {
            final ConfigContext configContext = getConfigContext();
            ConfigContextImpl.lock();
            //validate that the server exists and return its node agent
            final Target target = TargetBuilder.INSTANCE.createTarget(
                VALID_TYPES, serverName, configContext);  
            final NodeAgent controller = target.getNodeAgents()[0];
           
            //Remove the server instance
            final Domain domain = ConfigAPIHelper.getDomainConfigBean(configContext);           
            final Servers servers = domain.getServers();
            final Server server = target.getServers()[0];
            boolean isReachable = true;

            try {               
                ServerRuntimeMBean serverMBean = InstanceProxy.getInstanceProxy(serverName);
                Status status = serverMBean.getRuntimeStatus().getStatus();
            } catch (Exception ex) {
                if (InstanceProxy.isUnreachable(ex)) {
                    isReachable = false;
                }
            }

            if(isReachable)
                throw new InstanceException(_strMgr.getString("serverIsNotStopped",
                    serverName));
           
            if (ServerHelper.isServerStandAlone(configContext, serverName)) {
                //If the server instance is stand-alone, we must remove its stand alone
                //configuration after removing the server instance (since a configuration
                //can only be deleted if it is unreferenced). Unfortunately, if
                //this fails, we leave an unreferenced standalone configurtion.               
                String configName = server.getConfigRef();
                // remove the server
                servers.removeServer(server, OVERWRITE);           
                //remove the standalone configuration               
                //FIXTHIS: One issue is that the call below will result in a call to flushAll
                //which is also called below. This must be taken into account when we
                //figure out the notification story.
                getConfigsConfigBean().deleteConfiguration(configName);
            } else {
                if (ServerHelper.isServerClustered(configContext, server)) {
                    //If the instance is clustered, the we must remove the server refs from
                    //the cluster.
                    deleteClusterReferences(serverName);
                }               
                //Remove the server
                servers.removeServer(server, OVERWRITE);    
            }
           
            //Remove our connction to the server instance
            InstanceRegistry.removeInstanceConnection(serverName);
           
            //Notify the node agent that a new server has been deleted to it so it can
            //resynchronize.
            //FIXTHIS: We force persistence, clear any notifications, and update the
            //Application server's config context explicitely. Until this is modelled
            //as an event notification (TBD) we need this to happen before notifying or
            //the Node Agent will not synchronize the correct data.
            //QUESTION: What happens if an exception is thrown above (e.g. in addNodeAgent). How do
            //we restore the admin config context to its previous (and unpersisted value)???
            flushAll();
            NodeAgentMBean agentMBean = NodeAgentProxy.getNodeAgentProxy(controller.getName());                       
            agentMBean.synchronizeWithDAS();
        } catch (Exception ex) {
            throw getExceptionHandler().handleInstanceException(
                ex, "eeadmin.deleteServerInstance.Exception", serverName);
        } finally {
            ConfigContextImpl.unlock();
        }      
    }
          
    private void addServerProperties(Server server, Properties props) throws ConfigException
    {
        //Set the server instances properties.
        //FIXTHIS: Should we be setting properties of standalone instances, since
        //the properties are already set in the stand alone configuration?
        if (props != null) {
            for (Enumeration e = props.propertyNames() ; e.hasMoreElements() ;) {
                String name = (String)e.nextElement();
                String value = (String)props.getProperty(name);               
                //Add the new property
                if (value != null) {
                    //Remove the property if it already exists
                    SystemProperty sysProp = server.getSystemPropertyByName(name);
                    if (sysProp != null) {                       
                        server.removeSystemProperty(sysProp, OVERWRITE);
                    }
                    SystemProperty ep = new SystemProperty();
                    ep.setName(name);
                    ep.setValue(value);
                    server.addSystemProperty(ep, OVERWRITE);                   
                }
            }
        }
    }          
           
    protected void addApplicationReference(Object server, boolean enabled, String name,
        String virtualServers) throws ConfigException
    {       
        ApplicationRef ref = new ApplicationRef();
        ref.setEnabled(enabled);
        ref.setRef(name);
        if (virtualServers != null) {
            ref.setVirtualServers(virtualServers);
        }
        ((Server)server).addApplicationRef(ref, OVERWRITE);       
    }
       
    protected void addResourceReference(Object server, boolean enabled, String name)
        throws ConfigException
    {
        ResourceRef ref = new ResourceRef();
        ref.setEnabled(enabled);
        ref.setRef(name);
        ((Server)server).addResourceRef(ref, OVERWRITE);       
    }
           
    private void createStandAloneServerInstance(
        Server server, Properties props) throws ConfigException, InstanceException
    {               
        //Create the standalone configuration to be referenced by the server.
        //FIXTHIS: One issue is that the call below will result in a call to flushAll
        //which is also called below. This must be taken into account when we
        //figure out the notification story.
        String standaloneConfigName = getConfigsConfigBean().createStandAloneConfiguration(
            server.getName(), props);
       
        //Create the server instance referencing this new standalone configuration
        createSharedServerInstance(standaloneConfigName, server, null);
    }
   
    private void createClusteredServerInstance(String clusterName,
        Server server, Properties props) throws ConfigException
    {
        final ConfigContext configContext = getConfigContext();
        //Add properties
        addServerProperties(server, props);
       
        //Get the configuration specified by configName and ensure that it exists
        Cluster cluster = ClusterHelper.getClusterByName(configContext,
            clusterName);
       
       
        //The clustered server inherits its configuration from the cluster
        server.setConfigRef(cluster.getConfigRef());

        //Now add the new server instance
        // to avoid Validator's complains
        Domain domain = ConfigAPIHelper.getDomainConfigBean(configContext);
        domain.getServers().addServer(server, OVERWRITE);                       
       
        //Add the server to the cluster
        ServerRef serverRef = new ServerRef();
        serverRef.setRef(server.getName());
        cluster.addServerRef(serverRef, OVERWRITE);
       
       
        //The clustered server inherits its applications from the cluster
        ApplicationRef[] appRefs = cluster.getApplicationRef();       
        for (int i = 0; i < appRefs.length; i++) {
            addApplicationReference(server, appRefs[i].isEnabled()
                appRefs[i].getRef(), appRefs[i].getVirtualServers());
        }
       
        //The clustered server inherits its resources from the cluster
        ResourceRef[] resRefs = cluster.getResourceRef();
        ResourceRef resRef = null;
        for (int i = 0; i < resRefs.length; i++) {
            addResourceReference(server, resRefs[i].isEnabled(),
                resRefs[i].getRef());
        }
    }
   
    private void createSharedServerInstance(String configName,
        Server server, Properties props) throws ConfigException, InstanceException
    {       
        final ConfigContext configContext = getConfigContext();
       
        //Get the configuration specified by configName and ensure that it exists
        //and is valid
        Config config = validateSharedConfiguration(configContext, configName);
       
        server.setConfigRef(configName);
       
        //Add properties
        addServerProperties(server, props);
       
        //Add system applications and resources
        addSystemApplications(server);
        addSystemResources(server);
        //Finally add the new server instance
        Domain domain = ConfigAPIHelper.getDomainConfigBean(configContext);
        domain.getServers().addServer(server, OVERWRITE);                       
    }
   
    /**
     * Choose non-conflicting port numbers. Warning the incoming portsInUse is side
     * affected, so that the PortInUse elements are modified to contain the new port.
     */
    private ArrayList pickNonConflictingPorts(Server server, ArrayList portsInUse)
        throws ConfigException
    {       
        Properties props = new Properties();
        PortInUse portInUse;
        int port;
       
        //We only want to check for port conflicts if the node agent specified has rendezvous'd;
        //otherwise, the host name on which it is residing is unknown (defaulting to "localhost").
        //Before we can indicate whether a port is in use, we must know the valid host name.
        final boolean isBoundToHost = getPortConflictCheckerConfigBean().isBoundToHost(server);
       
        //Iterate through all the conflicting ports and pick new values.
        for (int i = 0; i < portsInUse.size(); i++) {
            portInUse = (PortInUse)portsInUse.get(i);
            port = portInUse.getPort();
            int newPort = 0;
            if (isBoundToHost) {
                newPort = NetUtils.getNextFreePort(portInUse.getHostName(), port);           
            } else {
                newPort = port + 1;
            }
            //Keep track of the newly assigned and non-conflicting port. WARNING: we are
            //side affecting the incoming ArrayList.
            portInUse.setNewPort(newPort);
            //Build the list of system properties to add to the server instance
            props.put(portInUse.getPropertyName(), new Integer(newPort).toString());
        }
        addServerProperties(server, props);
        return portsInUse;
    }
        
    /**
     * Check to see if any of the ports defined as system properties are in use or conflict with
     * other ports in domain.xml (i.e. with other server instances on the same machine -- with
     * the same node agent). If there are conflicts, then we pick new port numbers.
     */
    private ArrayList resolvePortConflicts(Server server, Properties newProps) throws Exception
    {
        PortConflictCheckerConfigBean portChecker = getPortConflictCheckerConfigBean();
        String serverName = server.getName();
        ArrayList portsInUse = null;       
        try {
            //First check to see whether any of the user specified ports are in use, if
            //so an exception must be thrown
            if (newProps != null) {
                portChecker.checkForPortConflicts(server, newProps, newProps, false);
            }
           
            int i = 0;           
            //We loop trying trying to incrementally assign new ports.
            while (true) {
                //Perform some sort of sanity check to ensure
                //that the port numbers do not conflict for other servers on the same
                //node agent. This is accomplished by comparing properties whose
                //name contains "port" and whose value is numeric. NOTE: port validation
                //is done after adding the server. For this reason, we must rollback the
                //addition of the server if the port check fails.
                try {
                    portChecker.checkForPortConflicts(server, null, false);
                    //stop when there are no port conflicts
                    break;
                } catch (PortInUseException ex) {                          
                    if (i++ > 25) {
                        //We do not want to throw the PortInUseException since it is an internal
                        //class and protected.
                        throw new InstanceException(ex.getMessage());
                    }
                    //If there were port conflicts, then we pick unused ports.
                    ArrayList newPorts = pickNonConflictingPorts(server, ex.getConflictingPorts());
                   
                    //Keep track of the initial list of conflicting ports. This is tricky
                    //since the list in the PortInUseException will shrink as conflicts
                    //are resolved.
                    if (portsInUse == null) {
                        portsInUse = newPorts;
                    } else {
                        //Now take all the newly resolved ports and apply them to the original list, updating
                        //only the new port.
                        for (int j = 0; j < newPorts.size(); j++) {
                            PortInUse newPort = (PortInUse)newPorts.get(j);                       
                            for (int k = 0; k < portsInUse.size(); k++) {
                                PortInUse port = (PortInUse)portsInUse.get(k);
                                if (port.getPropertyName().equals(newPort.getPropertyName())) {
                                    port.setNewPort(newPort.getNewPort());
                                    break;
                                }
                            }
                        }
                    }
                }                       
            }
        } catch (Exception ex) {               
            try {
                deleteServerInstance(serverName);
            } catch (Exception ex2) {
                //Log         
                StringManagerBase sm = StringManagerBase.getStringManager(getLogger().getResourceBundleName());           
                getLogger().log(Level.WARNING,
                   sm.getString("eeadmin.createServerInstance.Exception", serverName), ex2);
            }
            throw (ex);
        }
        return portsInUse;
    }
   
    /**
     * Creates a new server instance. This operation is invoked by the asadmin create-instance
     * command.
     */
    public void createServerInstance(
        String nodeAgentName, String serverName,
        String configName, String clusterName, Properties props)
        throws InstanceException, PortReplacedException
    {
        ArrayList conflictingPorts = null;
        try {                       
            final ConfigContext configContext = getConfigContext();
            ConfigContextImpl.lock();
            //validate name uniqueness
            if (!ConfigAPIHelper.isNameUnique(configContext, serverName)) {
                 throw new InstanceException(_strMgr.getString("serverNameNotUnique",
                    serverName));
            }
           
      ConfigAPIHelper.checkLegalName(serverName);
     
            // see if nodeagent exists, if not create an empty reference
            Domain domain = ConfigAPIHelper.getDomainConfigBean(configContext);           
            NodeAgents agents=domain.getNodeAgents();
            NodeAgent agent=agents.getNodeAgentByName(nodeAgentName);
            if (agent == null) {
                // create an implnodeagent reference
                NodeAgentsConfigBean naMBean = getNodeAgentsConfigBean();
                naMBean.createNodeAgentConfig(nodeAgentName);
            }                   
           
            //a configuration and cluster cannot both be specified
            if (configName != null && clusterName != null) {
                throw new InstanceException(_strMgr.getString("configAndClusterMutuallyExclusive"));
            }           
           
            //Ensure that server specified by serverName does not already exist.
            //Given that we've already checked for uniqueness earlier, this should never
            //be the case, but we'll be extra safe here.
            Servers servers = domain.getServers();
            Server server = servers.getServerByName(serverName);
            if (server != null) {
                throw new InstanceException(_strMgr.getString("serverAlreadyExists",
                    serverName));
            }                           
           
            //Create the new server instance
            server = new Server();           
            server.setNodeAgentRef(nodeAgentName);
            server.setName(serverName);                               
           
            if (configName != null) {
                createSharedServerInstance(configName, server, props);
            } else if (clusterName != null) {
                createClusteredServerInstance(clusterName, server, props);
            } else {
                //FIXTHIS: One issue is that the call below will result in a call to flushAll
                //which is also called below. This must be taken into account when we
                //figure out the notification story.
                createStandAloneServerInstance(server, props);
            }                                                  
           
           
            //Check for and resolve port conflicts. The list of port conflicts is maintained.
            //This is called after creating the server. This is due to the fact that port
            //conflicts are resolved and a marker PortReplacedException is thrown; however
            //the server is still created.
            conflictingPorts = resolvePortConflicts(server, props);
           
            //Notify the node agent that a new server has been added to it so it can
            //resynchronize.
            //FIXTHIS: We force persistence, clear any notifications, and update the
            //Application server's config context explicitely. Until this is modelled
            //as an event notification (TBD) we need this to happen before notifying or
            //the Node Agent will not synchronize the correct data.
            //QUESTION: What happens if an exception is thrown above (e.g. in addNodeAgent). How do
            //we restore the admin config context to its previous (and unpersisted value)???
            flushAll();
            NodeAgentMBean agentMBean = NodeAgentProxy.getNodeAgentProxy(nodeAgentName);                       
            agentMBean.synchronizeWithDAS();                          
        } catch (Exception ex) {
            throw getExceptionHandler().handleInstanceException(
                ex, "eeadmin.createServerInstance.Exception", serverName);
        } finally {
            ConfigContextImpl.unlock();
        }
        //Finally after all is said and done, we throw an exception if there were port
        //conflicts.
        if (conflictingPorts != null) {
            throw new PortReplacedException(conflictingPorts);
        }
    }     
   
    private String[] toStringArray(Server[] sa)
    {
        int numServers = sa.length;
        final String[] result = new String[numServers];
        for (int i = 0; i < numServers; i++)
        {
            result[i] = sa[i].getName();
        }
        return result;
    }
   
    private PropertyConfigBean getPropertyConfigBean() {
        return new PropertyConfigBean(getConfigContext());
    }
   
    private NodeAgentsConfigBean getNodeAgentsConfigBean()
    {
        return new NodeAgentsConfigBean(getConfigContext());
    }
   
    private ConfigsConfigBean getConfigsConfigBean()
    {
        return new ConfigsConfigBean(getConfigContext());
    }   
   
    private PortConflictCheckerConfigBean getPortConflictCheckerConfigBean()
    {
        return new PortConflictCheckerConfigBean(getConfigContext());
    }
}
TOP

Related Classes of com.sun.enterprise.ee.admin.configbeans.ServersConfigBean$GetRuntimeStatusTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.