/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (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/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */

/*
 * DomainsProcessor.java
 *
 * Created on November 20, 2003, 10:45 AM
 */

package com.sun.enterprise.tools.upgrade.common;

import java.util.*;
import java.io.*;
import java.util.logging.*;
import java.net.InetAddress;
import java.net.UnknownHostException;

import com.sun.enterprise.util.ASenvPropertyReader;
import com.sun.enterprise.util.SystemPropertyConstants;

import com.sun.enterprise.tools.upgrade.logging.*;
import com.sun.enterprise.cli.framework.*;
import com.sun.enterprise.util.i18n.StringManager;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerConfigurationException;

import javax.xml.transform.dom.DOMSource;  
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.OutputKeys;

import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.sun.enterprise.tools.upgrade.cluster.*;

/**
 *
 * @author  prakash
 * @author  hans
 */


public class DomainsProcessor {
    private static CommonInfoModel commonInfo;
    private java.util.Vector httpSSLPorts;
    private java.util.Vector iiopSSLPorts;
    private java.util.Vector iiopMutualAuthPorts;
    private java.util.Vector sourceXMLCorePorts;
    private static int adminPortToStartWith = 4858;
    
    private static Logger logger = LogService.getLogger(LogService.UPGRADE_LOGGER);
    private static StringManager stringManager = StringManager.getManager(LogService.UPGRADE_LOGGER);
    
    /** Creates a new instance of DomainsProcessor */
    public DomainsProcessor(CommonInfoModel ci) {
        this.commonInfo = ci;
        httpSSLPorts = new java.util.Vector();
        iiopSSLPorts = new java.util.Vector();
        iiopMutualAuthPorts = new java.util.Vector();
        sourceXMLCorePorts = new java.util.Vector();
        // Prefill with ports used in default domain and samples domain.
        // default domain xml file ports:
        File domainDir =  new File(ci.getTargetDomainRoot() + File.separator + "domain1");
        if(!domainDir.exists()){
            // This could be due to the reason that its inplace upgrade.  In this case upgrade tool should create the default domain too.
        }
        String targetDomainFile = ci.getTargetDomainRoot() + File.separator + "domain1"+File.separator+
        "config"+File.separator+"domain.xml" ;
        if(domainDir.isDirectory() && !(ci.isValid70Domain(ci.getTargetDomainRoot() + File.separator + "domain1")) && (new File(targetDomainFile)).exists())  {
            
            String htSSP = getPortFromXML(targetDomainFile, "http-listener", "http-listener-2");
            if(htSSP != null) httpSSLPorts.add(htSSP);
            String iiSSP = getPortFromXML(targetDomainFile, "iiop-listener", "SSL");
            if(iiSSP != null) iiopSSLPorts.add(iiSSP);
            String iiMAP = getPortFromXML(targetDomainFile, "iiop-listener", "SSL_MUTUALAUTH");
            if(iiMAP != null) iiopMutualAuthPorts.add(iiMAP);
        }
        File samplesDir =  new File(ci.getTargetDomainRoot() + File.separator + "samples");
        if(samplesDir.isDirectory() && !(ci.isValid70Domain(ci.getTargetDomainRoot() + File.separator + "samples")) )   {
            // Now add sample domain ports if there is one
            String sampleDomainFile = ci.getTargetDomainRoot() + File.separator + "samples"+File.separator+"config"+File.separator+"domain.xml" ;
            if(new File(sampleDomainFile).exists()){
                String shtSSP = getPortFromXML(sampleDomainFile, "http-listener", "http-listener-2");
                if(shtSSP != null) httpSSLPorts.add(shtSSP);
                String siiSSP = getPortFromXML(sampleDomainFile, "iiop-listener", "SSL");
                if(siiSSP != null) iiopSSLPorts.add(siiSSP);
                String siiMAP = getPortFromXML(sampleDomainFile, "iiop-listener", "SSL_MUTUALAUTH");
                if(siiMAP != null) iiopMutualAuthPorts.add(siiMAP);
            }
        }
        
        
        // Store source xml ports core ports: http,iiop,jms
        // TO-DO collect these ports from all source domains iteratively and store them in sourceXMLCorePorts vector
        // Only for testing purposes.....
    }
    private DomainsProcessor(CommonInfoModel ci, boolean nothing) {
        
    }
    
    public void processTargetDomains() throws HarnessException{
        List domainNames = commonInfo.getDomainList();
        String target = commonInfo.getTargetInstallDir();
        
        //Following lines are copied from IasAdminCommand
        ASenvPropertyReader reader = new ASenvPropertyReader(System.getProperty(SystemPropertyConstants.CONFIG_ROOT_PROPERTY));
        reader.setSystemProperties();
        //initGlobalsManager(null);
        //IasAdminCommand end
        for(int i=0; i<domainNames.size();i++) {
            String sourceDomainName = (String)domainNames.get(i);
            String targetDomainName=sourceDomainName;
            if(!new File(commonInfo.getTargetDomainRoot()).isDirectory()) {
                logger.log(Level.INFO,stringManager.getString("enterprise.tools.upgrade.not_valid_target_install"));
                return;
            }
            File targetDomainUpgrade = new File(commonInfo.getTargetDomainRoot()+File.separator+targetDomainName);
            // I think below condition is reduntant with the all conditions inside
            if(!targetDomainUpgrade.isDirectory() || commonInfo.checkSourceInputAsDomainRoot(commonInfo.getSourceInstallDir())){
                File targetDomainUpgrade80=new File(commonInfo.getTargetDomainRoot()+File.separator+targetDomainName);
                if(targetDomainUpgrade80.isDirectory())   {
                    this.setAdminPortAndSecurity(sourceDomainName,targetDomainName);
                    continue;
                }
                String[] createDomainCommand = this.getCreateDomainCommand(sourceDomainName,targetDomainName);
                boolean canContinue = executeCommand(createDomainCommand);
                UpdateProgressManager.getProgressManager().setContinueUpgrade(canContinue);               
                if(!canContinue) {
                    throw new HarnessException(stringManager.getString("enterprise.tools.upgrade.domain_creation_error", targetDomainName));
                }
                UpdateProgressManager.getProgressManager().processUpgradeUpdateEvent((i*30)/domainNames.size());
            }
            this.setAdminPortAndSecurity(sourceDomainName,targetDomainName);                
        }
        //this.processDomainInstances();
    }
    
    private String[] getCreateDomainCommand(String domainName, String domainName80) {
        /**
         * Port type                     Appserver 8.0                  Appserver 7.0
         * 1. Http                        8080  http-listener-1          80 or 1024- http-listener-1
         * 2. http_ssl                    1043   - http-listener-2       -------- dont know --------
         * 3. JMS                         7676  - default_jms_host       7676 - jms-service
         * 4. IIOP                        3700  - orb-listener-1         3700 - orb-listener-1
         * 5. iiop_ssl                    1060 - ssl                     ---------- dont know -------
         * 6. iiop_mutual_auth            1061 -ssl-math                 ----------   dont know -----
         * 7. admin port                  4848  - admin-listener (httplistener)    4848 - stored in admin-server server.xml
         *
         * http, jms, iiop, and admin ports are transferred from appserver 7.0.
         * Need to pick up appropriate ports for http_ssl, iiop_ssl and iiop_mutual_auth.
         */
        String target = commonInfo.getTargetInstallDir();
        String adminPort = getSourceAdminPort(((DomainInfo)this.commonInfo.getDomainMapping().get(domainName)).getDomainPath());
        // http, iiop, jms ports are replaced by the migration anyway...
        String httpPort = "8080";
        String jmsPort = "7676";
        String iiopPort = "3700";
        
        // Now I need a unique ports for http-ssl,iiop-ssl,iiop-mutual-auth
        String httpSSLPort = getAFreePort(1044,10);
        String iiopSSLPort = getAFreePort(1090,10);
        String iiopSSLMutualAuth = getAFreePort(1091,10);
        //START CR 6397215
        String adminJMXPort = getAFreePort(8687,10);
        //END CR 6397215
        
        httpSSLPorts.add(httpSSLPort);
        iiopSSLPorts.add(iiopSSLPort);
        iiopMutualAuthPorts.add(iiopSSLMutualAuth);
        String propertiesString = "http.ssl.port="+httpSSLPort+":orb.ssl.port="+iiopSSLPort+":orb.mutualauth.port="+iiopSSLMutualAuth+
            ":jms.port="+jmsPort+":orb.listener.port="+iiopPort;  
        
        //START CR 6397215
        // if we are upgrading from 8.x PE to 9.0 PE we need to specify a 
        // JMX connector port
        if(commonInfo.checkUpgradefrom8xpeto90pe()) {
            propertiesString = propertiesString+":domain.jmxPort="+adminJMXPort;
        }
        //END CR 6397215
        String [] createDomainCommand = {"create-domain",
         "--domaindir",
            "\"" + commonInfo.getTargetDomainRoot() +"\"",
            "--adminport",
            adminPort,
            "--adminuser",
            commonInfo.getAdminUserName(),
            "--passwordfile ",
            "\"" + commonInfo.getPasswordFile() +"\"",
            "--domainproperties",
            propertiesString,
            domainName80
            };            
           return createDomainCommand;
 
    }
    
    public static String getSourceAdminPort() {
        return getSourceAdminPort(commonInfo.getSourceDomainPath());
    }
    
    // This method returns admin port from admin-server server.xml
    public static String getSourceAdminPort(String domainPath) {
        // Get the admin port from server.xml of admin-server
        if(commonInfo.getSourceVersion().equals(UpgradeConstants.VERSION_7X)) {
            String adminServerXmlFile = domainPath+File.separator+"admin-server"+File.separator+"config"+File.separator+"server.xml";
            String port = getPortFromXML(adminServerXmlFile,"http-listener", "http-listener-1");
            if(port != null)
                return port;
        }else{
            // For 8.x get it from domain.xml
            String domainXmlFile = domainPath+File.separator+"config"+File.separator+"domain.xml";
            if(new File(domainXmlFile).exists()){
                String port = getPortFromXML(domainXmlFile,"http-listener", "admin-listener");
                if(port != null)
                    return port;
            }
        }
        // return some default no....user should change it later.
        adminPortToStartWith =+10;
        return String.valueOf(adminPortToStartWith);
    }
    public static String getSourceAdminSecurity(String domainPath) {
        // Get the admin security-enabled from server.xml of admin-server
        if(commonInfo.getSourceVersion().equals(UpgradeConstants.VERSION_7X)) {
            String adminServerXmlFile = domainPath+File.separator+"admin-server"+File.separator+"config"+File.separator+"server.xml";
            String securityEnabled = getSecurityEnabledFromXML(adminServerXmlFile,"http-listener", "http-listener-1");
            if(securityEnabled != null)
                return securityEnabled;
        }else{
            // For 8.x get it from domain.xml
            String domainXmlFile = domainPath+File.separator+"config"+File.separator+"domain.xml";
            if(new File(domainXmlFile).exists()){
                String securityEnabled = getSecurityEnabledFromXML(domainXmlFile,"http-listener", "admin-listener");
                if(securityEnabled != null)
                    return securityEnabled;
            }
        }
        return "true"; // default to true
    }
    
    public static String getSourceAdminSecurity() {
        String domainPath = commonInfo.getSourceDomainPath();
        return getSourceAdminSecurity(domainPath);
    }
    private void setAdminPortAndSecurity(String sourceDomainName, String targetDomainName){
        String domainPath = ((DomainInfo)this.commonInfo.getDomainMapping().get(sourceDomainName)).getDomainPath();
        String adminPort = getSourceAdminPort(domainPath);
        String securityEnabled = getSourceAdminSecurity(domainPath);
        
        String domainFileName = commonInfo.getTargetDomainRoot()+File.separator+targetDomainName+File.separator+"config"+File.separator+"domain.xml";
        
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //factory.setValidating(true);
        factory.setNamespaceAware(true);
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver((org.xml.sax.helpers.DefaultHandler)Class.forName
            ("com.sun.enterprise.config.serverbeans.ServerValidationHandler").newInstance());
            Document resultDoc = builder.parse( new File(domainFileName));
            NodeList taggedElements = resultDoc.getDocumentElement().getElementsByTagName("http-listener");
            for(int lh =0; lh < taggedElements.getLength(); lh++){
                Element element = (Element)taggedElements.item(lh);
                // Compare id attribute of http-listener elements.
                if((element.getAttribute("id")).equals("admin-listener")){
                    element.setAttribute("port",adminPort);
                    element.setAttribute("security-enabled", securityEnabled);
                    break;
                }
            }
            
          // Use a Transformer for output
          TransformerFactory tFactory = TransformerFactory.newInstance();
          Transformer transformer = tFactory.newTransformer();
          if (resultDoc.getDoctype() != null){
                String systemValue = resultDoc.getDoctype().getSystemId();
                transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, systemValue);
                String pubValue = resultDoc.getDoctype().getPublicId();
                transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, pubValue);
          } 

          DOMSource source = new DOMSource(resultDoc);
          StreamResult result = new StreamResult(new FileOutputStream(domainFileName));
          transformer.transform(source, result);
          result.getOutputStream().close();
          
        }catch (Exception ex){
            logger.log(Level.WARNING, stringManager.getString("domainProcessor.portFromXML"),ex);
            //throw new HarnessException(stringManager.getString("upgrade.transform.startFailureMessage"));
        }
        
    }
    private static String getPortFromXML(String fileName, String tagName, String id) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //factory.setValidating(true);
        factory.setNamespaceAware(true);
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver((org.xml.sax.helpers.DefaultHandler)Class.forName
            ("com.sun.enterprise.config.serverbeans.ServerValidationHandler").newInstance());
            Document adminServerDoc = builder.parse( new File(fileName));
            NodeList taggedElements = adminServerDoc.getDocumentElement().getElementsByTagName(tagName);
            for(int lh =0; lh < taggedElements.getLength(); lh++){
                Element element = (Element)taggedElements.item(lh);
                // Compare id attribute of http-listener elements.
                if((element.getAttribute("id")).equals(id)){
                    return element.getAttribute("port");
                }
            }
        }catch (Exception ex){
            logger.log(Level.WARNING, stringManager.getString("domainProcessor.portFromXML"),ex);
            //throw new HarnessException(stringManager.getString("upgrade.transform.startFailureMessage"));
        }
        return null;
    }
    
    private static String getSecurityEnabledFromXML(String fileName, String tagName, String id) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //factory.setValidating(true);
        factory.setNamespaceAware(true);
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver((org.xml.sax.helpers.DefaultHandler)Class.forName
            ("com.sun.enterprise.config.serverbeans.ServerValidationHandler").newInstance());
            Document adminServerDoc = builder.parse( new File(fileName));
            NodeList taggedElements = adminServerDoc.getDocumentElement().getElementsByTagName(tagName);
            for(int lh =0; lh < taggedElements.getLength(); lh++){
                Element element = (Element)taggedElements.item(lh);
                // Compare id attribute of http-listener elements.
                if((element.getAttribute("id")).equals(id)){
                    return element.getAttribute("security-enabled");
                }
            }
        }catch (Exception ex){
            logger.log(Level.WARNING, stringManager.getString("domainProcessor.adminSecureFromXML"),ex);
            //throw new HarnessException(stringManager.getString("upgrade.transform.startFailureMessage"));
        }
        return null;
    }
    
    private String getTargetNodeAgentName(String domainName, CommonInfoModel commonInfoMod){
        String configFileName = commonInfoMod.getTargetDomainRoot()+File.separator+domainName+File.separator+"config"+File.separator+"domain.xml";
        return getNodeAgentNameFromXML(configFileName);
    }
    
    private String getNodeAgentNameFromXML(String fileName) {
        if(commonInfo.getSourceVersion().equals(UpgradeConstants.VERSION_7X) || ! new File(fileName).exists()) {
            return null;
        }
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //factory.setValidating(true);
        factory.setNamespaceAware(true);
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver((org.xml.sax.helpers.DefaultHandler)Class.forName
            ("com.sun.enterprise.config.serverbeans.ServerValidationHandler").newInstance());
            Document adminServerDoc = builder.parse( new File(fileName));
            NodeList taggedElements = adminServerDoc.getDocumentElement().getElementsByTagName("node-agent");
            Element element = (Element)taggedElements.item(0);
            return element.getAttribute("name");
        }catch (Exception ex){
            logger.log(Level.WARNING, stringManager.getString("domainProcessor.nodeAgentFromXML"),ex);
            //throw new HarnessException(stringManager.getString("upgrade.transform.startFailureMessage"));
        }
        return null;
    }
    private boolean isNodeAgentExists(String agentName, String fileName){
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //factory.setValidating(true);
        factory.setNamespaceAware(true);
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver((org.xml.sax.helpers.DefaultHandler)Class.forName
            ("com.sun.enterprise.config.serverbeans.ServerValidationHandler").newInstance());
            Document adminServerDoc = builder.parse( new File(fileName));
            NodeList taggedElements = adminServerDoc.getDocumentElement().getElementsByTagName("node-agent");
            for(int lh =0; lh < taggedElements.getLength(); lh++){
                Element itElement = ((Element)taggedElements.item(lh));
                String attrName = itElement.getAttribute("name");
                if(attrName.equals(agentName))
                    return true;
                // If the agentName contains .  example beacon.east, then should only compare to beacon.
                if(agentName.indexOf(".") != -1){
                    if(agentName.substring(0,agentName.indexOf(".")).equals(attrName)){
                        return true;
                    }
                }
            }
        }catch (Exception ex){
            logger.log(Level.WARNING, stringManager.getString("domainProcessor.nodeAgentFromXML"),ex);
            //throw new HarnessException(stringManager.getString("upgrade.transform.startFailureMessage"));
        }
        return false;
    }
    
    public static String getTargetDomainPort(String domainName, CommonInfoModel commonInfoMod){
        String configFileName = commonInfoMod.getTargetDomainRoot()+File.separator+domainName+File.separator+"config"+File.separator+"domain.xml";
        return getPortFromXML(configFileName, "http-listener", "admin-listener");
    }
    
    public static String getTargetDomainSecurity(String domainName, CommonInfoModel commonInfoMod){
        String configFileName = commonInfoMod.getTargetDomainRoot()+File.separator+domainName+File.separator+"config"+File.separator+"domain.xml";
        return getSecurityEnabledFromXML(configFileName, "http-listener", "admin-listener");
    }
    
    private String getAFreePort(int initPortNumber, int increment){
        // Do this only for 20 iterations.  If you cant find one in 10 iterations, then just assign some random number.
        int portNumber = initPortNumber;
        for(int i=0; i<20; i++){
            if(isPortNumberUsable(portNumber))
                return Integer.toString(portNumber);
            portNumber +=increment;
        }
        // In 20 iterations, if we cant find a free port, just return the last port number itereated.
        return Integer.toString(portNumber);
    }
    private boolean isPortNumberUsable(int portNumber){
        // First check if this port exists in any of the lists we have
        String portString = Integer.toString(portNumber);
        for(int i=0; i<httpSSLPorts.size(); i++){
            if(((String)httpSSLPorts.get(i)).equals(portString))
                return false;
        }
        for(int i=0; i<iiopSSLPorts.size(); i++){
            if(((String)iiopSSLPorts.get(i)).equals(portString))
                return false;
        }
        for(int i=0; i<iiopMutualAuthPorts.size(); i++){
            if(((String)iiopMutualAuthPorts.get(i)).equals(portString))
                return false;
        }
        for(int i=0; i<sourceXMLCorePorts.size(); i++){
            if(((String)sourceXMLCorePorts.get(i)).equals(portString))
                return false;
        }
        // This NetUtils class is in appserv-commons module.
        return com.sun.enterprise.util.net.NetUtils.isPortFree(portNumber);
    }
    private java.util.List getInstanceNamesWithoutAdminServerAndServer1(java.util.List instanceList){
        java.util.List newList = new java.util.ArrayList();
        for(java.util.Iterator it = instanceList.iterator(); it.hasNext();){
            String serverName = (String)it.next();
            if(serverName.equals("admin-server")) //|| serverName.equals("server1"))
                continue;
            newList.add(serverName);
        }
        return newList;
    }
    public void processDomainInstances() throws HarnessException {
        // This method creates instances in target installation for every server instance existing in source.
        java.util.Hashtable domainMapping = commonInfo.getDomainMapping();
        
        // Make sure that this is not called on PE
        // Safety check
        if(commonInfo.getTargetEdition().equals(UpgradeConstants.EDITION_PE)){
            return;
        }
        for(java.util.Enumeration domains = domainMapping.keys();domains.hasMoreElements();){
            DomainInfo dInfo = (DomainInfo)domainMapping.get((String)domains.nextElement());
            // creation of server instances required only if there more than 2 servers
            // Is this is valid?   admin-server and server1 are default ones.
            // Fixed:  Many a time when domains are created for 7.x appservers, it does create only admin-server and may not create server1
            //if(dInfo.getInstanceNames().size() > 2){
            boolean domainStarted = false;
            //if(this.getInstanceNamesWithoutAdminServer(dInfo.getInstanceNames()).size() > 1){
            if(this.getInstanceNamesWithoutAdminServerAndServer1(dInfo.getInstanceNames()).size() > 0){
                // get adminport and adminhost name for the domain.
                String adminPort = this.getTargetDomainPort(dInfo.getDomainName(),this.commonInfo);
                String adminSecurity = this.getTargetDomainSecurity(dInfo.getDomainName(),this.commonInfo);
                String agentName = getTargetNodeAgentName(dInfo.getDomainName(),this.commonInfo);
                //if agentName==null the installer did not create a node agent, so we do
                if ( agentName == null ) {
                    String hostName;
                    try {
                        hostName = (java.net.InetAddress.getLocalHost()).getHostName();
                        agentName = hostName + "_" + dInfo.getDomainName();
                    } catch (java.net.UnknownHostException uhe) {
                        hostName = "localhost";
                        agentName = dInfo.getDomainName() + "-agent";
                    }                   
                    createNodeAgent(agentName, hostName, adminPort, commonInfo.getAdminUserName(), commonInfo.getAdminPassword(),dInfo.getDomainName());
                }
                for(java.util.Iterator instanceNames = dInfo.getInstanceNames().iterator(); instanceNames.hasNext();){
                    String serverName = (String)instanceNames.next();
                    if(!serverName.equals("admin-server") &&
                    !commonInfo.getTargetEdition().equals(UpgradeConstants.EDITION_PE)) { //&& !serverName.equals("server1")){
                        if(!domainStarted){
                            if(!this.startDomain(dInfo.getDomainName())){
                                throw new HarnessException(stringManager.getString("domainProcessor.domainStartFailed",dInfo.getDomainName()));
                            }
                            domainStarted = true;
                        }
                        boolean status = this.createServerInstance(serverName, agentName, null, commonInfo.getAdminUserName(), commonInfo.getAdminPassword(), adminPort, adminSecurity);
                        if(!instanceNames.hasNext()){
                            if(domainStarted)
                                this.stopDomain(dInfo.getDomainName());
                        }
                    }
                }
            }
        }
    }
    
    public boolean createNodeAgent(String agentName, String dasHost,String dasPort, String dasuser, String daspwd, String domainName){
        String adminSecurity = DomainsProcessor.getTargetDomainSecurity(domainName, commonInfo);
        String[] command = {"create-node-agent", "--host",dasHost,"--port", dasPort, "--secure="+adminSecurity, "--user", dasuser, "--passwordfile ", "\"" + commonInfo.getPasswordFile() +"\"",
        agentName };
        return this.executeCommand(command);
    }
    
    public boolean createConfig(String configName){
        // Still dont know when to use.   will fill in whenever it is required
        return false;
    }
    
    public boolean createServerInstance(String serverName, String agentName, String configName, String userid, String pwd, String adminPort, String adminSecurity){
        // if  configName is null, then the command creates serverName_config
        // if nodeAgent does not exist, will create nodeAgent implicitely
        if(configName != null){
            String[] command = {"create-instance","--nodeagent",agentName,"--port",adminPort, "--secure="+adminSecurity, "--config", configName,
            "--user", userid, "--passwordfile ", "\"" + commonInfo.getPasswordFile() +"\"", serverName };
            return this.executeCommand(command);
        }else{
            //String[] command = {"create-instance","--nodeagent",agentName,
            //     "--user", userid, "--password", pwd, serverName };
            String[] command = {"create-instance","--nodeagent",agentName,
            "--user", userid, "--passwordfile ", "\"" + commonInfo.getPasswordFile() +"\"", "--port",adminPort,"--secure="+adminSecurity ,serverName };
            return this.executeCommand(command);
        }
    }
    
    private boolean startDomain(String domainName) {
        return startDomain(domainName, this.commonInfo);
    }
    
    public boolean startDomain(String domainName, CommonInfoModel commonInfo){
        return Commands.startDomain(domainName, commonInfo);
    }
    
    public boolean stopDomain(String domainName){
        return Commands.stopDomain(domainName, commonInfo);
    }
    
    private boolean executeCommand(String[] commandStrings){
        try {
            return Commands.executeCommand(commandStrings);
        } catch (com.sun.enterprise.cli.framework.CommandException ce) {
            //e.printStackTrace();
            Throwable t = ce.getCause();
            CommonInfoModel.getDefaultLogger().log(Level.SEVERE, stringManager.getString("enterprise.tools.upgrade.generalException", ce.getMessage()),ce);
            if (t != null) {
                CommonInfoModel.getDefaultLogger().severe(stringManager.getString("enterprise.tools.upgrade.generalException", t.getMessage()));
            }
        }
        return false;
    }
    public boolean processClusters() throws HarnessException {
        java.util.List clInfoList = ClustersInfoManager.getClusterInfoManager().getClusterInfoList();
        if((clInfoList == null) || (clInfoList.isEmpty()))
            return false;
        // Create cluster for each clInfoList.
        int clusterNo = 0;
        for(Iterator it = clInfoList.iterator(); it.hasNext(); ){
            ClusterInfo clInfo = (ClusterInfo)it.next();
            String clusterName = clInfo.getClusterName();
            if(clusterName == null)
                clusterName = "cluster_"+Integer.toString(clusterNo++);
            clInfo.setClusterName(clusterName);
            //this.createCluster(clusterName,clInfo.getMasterInstance().getDomain());
            this.createCluster(clusterName,clInfo.getDomainName());
            if(!this.commonInfo.getSourceVersion().equals(UpgradeConstants.VERSION_7X)){
                continue;
            }            
            List clInstances = clInfo.getClusteredInstanceList();
            ClusteredInstance masterInstance = clInfo.getMasterInstance();
            boolean domainStarted = false;
            String startedDomainName = null;
            String configName = configName = clusterName+"_config";
            if(masterInstance == null){
                // Is it guaranteed that there will be one master instance always?
                String adminPort = null;
                String adminSecurity = null;
                for(Iterator clInstIt = clInstances.iterator(); clInstIt.hasNext();){
                    ClusteredInstance clusteredInstance = (ClusteredInstance)clInstIt.next();
                    if(!domainStarted){
                        startedDomainName = clusteredInstance.getDomain();
                        if(!this.startDomain(startedDomainName)){
                            // Could not start domain.  Report the problem and break.
                            domainStarted = false;
                            throw new HarnessException(stringManager.getString("domainProcessor.domainStartFailed",startedDomainName));
                        }
                        adminPort = this.getTargetDomainPort(startedDomainName,this.commonInfo);
                        adminSecurity = this.getTargetDomainSecurity(startedDomainName,this.commonInfo);
                        domainStarted = true;
                    }
                    this.createClusteredInstance(clusteredInstance,clusterName,startedDomainName,configName,adminPort, adminSecurity);
                    if(!clInstIt.hasNext()){
                        if(domainStarted)
                            this.stopDomain(startedDomainName);
                    }
                }
            }else{
                if(this.startDomain(masterInstance.getDomain())){
                    domainStarted = true;
                    String adminPort = this.getTargetDomainPort(masterInstance.getDomain(),this.commonInfo);
                    String adminSecurity = this.getTargetDomainSecurity(masterInstance.getDomain(),this.commonInfo);
                    this.createClusteredInstance(masterInstance,clusterName,masterInstance.getDomain(),configName,adminPort, adminSecurity);
                    for(Iterator clInstIt = clInstances.iterator(); clInstIt.hasNext();){
                        ClusteredInstance clInst = (ClusteredInstance)clInstIt.next();
                        if(!clInst.isMaster())
                            this.createClusteredInstance(clInst,clusterName,masterInstance.getDomain(),configName,adminPort, adminSecurity);
                        if(!clInstIt.hasNext()){
                            if(domainStarted)
                                this.stopDomain(masterInstance.getDomain());
                        }
                    }
                }else{
                    throw new HarnessException(stringManager.getString("domainProcessor.domainStartFailed",masterInstance.getDomain()));
                }
            }
        }
        // Set currentCluster to null;
        this.commonInfo.setCurrentCluster(null);
        this.processStandAloneInstances();
        return true;
    }
    private boolean createClusteredInstance(ClusteredInstance clInstance, String clusterName, String domainName, String configName, String adminPort, String adminSecurity){
        String nodeAgentName = clInstance.getHost();
        String dasHostName = null;
        try {
            dasHostName = (java.net.InetAddress.getLocalHost()).getHostName();
        } catch (java.net.UnknownHostException uhe) {
            dasHostName = domainName;
        }
        if(nodeAgentName.equals("localhost")){
            nodeAgentName = dasHostName + "_" + domainName;
        } else {
            nodeAgentName = nodeAgentName + "_" + domainName;
        }
        String configFileName = commonInfo.getTargetDomainRoot()+File.separator+domainName+File.separator+"config"+File.separator+"domain.xml";
        if(!this.isNodeAgentExists(nodeAgentName,configFileName)){
            createNodeAgent(nodeAgentName, dasHostName, clInstance.getPort(), commonInfo.getAdminUserName(), commonInfo.getAdminPassword(),domainName);
        }
        //String property = http-listener-1-port=8078:HTTP_SSL_LISTENER_PORT=1041:IIOP_LISTENER_PORT=3698:IIOP_SSL_LISTENER_PORT=1051:IIOP_SSL_MUTUALAUTH_PORT=1052:JMX_SYSTEM_CONNECTOR_PORT=8688
        // I must use the data stored in clInstance to create the server instance by setting property.
        // Config name and cluster name cannot both be specified.
        String user = commonInfo.getAdminUserName();
        String password = commonInfo.getAdminPassword();
        String[] command = {"create-instance","--user", user, "--passwordfile ", "\"" + commonInfo.getPasswordFile() +"\"","--nodeagent",nodeAgentName,"--port",adminPort, "--secure="+adminSecurity,"--cluster",clusterName,clInstance.getInstanceName()};
        return this.executeCommand(command);
    }
    private boolean createCluster(String clusterName, String domainName){
        String adminSecurity = null;
        String adminPort = null;
        if(domainName != null){
            this.startDomain(domainName);
            adminPort = this.getTargetDomainPort(domainName, this.commonInfo);
            adminSecurity = this.getTargetDomainSecurity(domainName, this.commonInfo);
        }else{
            // This should be fixed.  This is not typical.  Domain name is a must.
        }
        String[] command = {"create-cluster","--port",adminPort, "--secure="+adminSecurity,"--user",commonInfo.getAdminUserName(),"--passwordfile ", "\"" + commonInfo.getPasswordFile() +"\"",clusterName};
        boolean returnStatus = this.executeCommand(command);
        this.stopDomain(domainName);
        return returnStatus;
    }
    public void processStandAloneInstances() throws HarnessException {
        if(!this.commonInfo.getSourceVersion().equals(UpgradeConstants.VERSION_7X)){
            // If the source is AS8.xEE then there server elements are migrated during transformation.
            return;
        } 
        List stdAloneInsts = UpgradeUtils.getUpgradeUtils(this.commonInfo).getStandAloneInstances(this.commonInfo.getDomainMapping());
        for(Iterator it = stdAloneInsts.iterator(); it.hasNext();){
            Vector instDInfo = (Vector)it.next();
            String serverName = (String)instDInfo.elementAt(0);
            DomainInfo dInfo = (DomainInfo)instDInfo.elementAt(1);
            String adminPort = this.getTargetDomainPort(dInfo.getDomainName(),this.commonInfo);
            String adminSecurity = this.getTargetDomainSecurity(dInfo.getDomainName(),this.commonInfo);
            String agentName = getTargetNodeAgentName(dInfo.getDomainName(),this.commonInfo);
            if(!this.startDomain(dInfo.getDomainName())){
                throw new HarnessException(stringManager.getString("domainProcessor.domainStartFailed",dInfo.getDomainName()));
            }
            if ( agentName == null ) {
                String hostName;
                try {
                    hostName = (java.net.InetAddress.getLocalHost()).getHostName();
                    agentName = hostName + "_" + dInfo.getDomainName();
                } catch (java.net.UnknownHostException uhe) {
                    hostName = "localhost";
                    agentName = dInfo.getDomainName() + "-agent";
                }
                createNodeAgent(agentName, hostName, adminPort, commonInfo.getAdminUserName(), commonInfo.getAdminPassword(),dInfo.getDomainName());
            }            
            if(!serverName.equals("admin-server")) { // && !serverName.equals("server1")){
                boolean status = this.createServerInstance(serverName, agentName, null, commonInfo.getAdminUserName(), commonInfo.getAdminPassword(),adminPort, adminSecurity);
            }
            this.stopDomain(dInfo.getDomainName());
        }
    }
}
