/*
 * 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.
 */

/*
 * Utils.java
 *
 * Created on April 19, 2004, 11:47 AM
 */

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

/**
 *
 * @author  prakash
 */
import java.io.*;
import java.util.*;
import java.util.logging.*;
import com.sun.enterprise.tools.upgrade.logging.*;
import com.sun.enterprise.util.i18n.StringManager;
import com.sun.enterprise.tools.upgrade.cluster.*;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;

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 com.sun.enterprise.tools.upgrade.transform.elements.BaseElement;
import sun.java2d.pipe.AATextRenderer;

public class UpgradeUtils {
    private static UpgradeUtils upgradeUtils;
    private StringManager stringManager = StringManager.getManager(LogService.UPGRADE_LOGGER);
    private static Logger logger=LogService.getLogger(LogService.UPGRADE_LOGGER);
    /** Creates a new instance of Utils */
    private static CommonInfoModel common;
    private UpgradeUtils(CommonInfoModel common) {
        this.common = common;
    }
    public static UpgradeUtils getUpgradeUtils(CommonInfoModel cim){
        //START CR 6348866
        if(upgradeUtils == null) {
            upgradeUtils = new UpgradeUtils(cim);
        } else {
            common = cim;
        }
        //END CR 6348866
        return upgradeUtils;
    }
    public Hashtable enlist70DomainsFromSource(CommonInfoModel cmi){
        String source = cmi.getSourceInstallDir();
        Hashtable domainMapping = null;
        if(!checkSourceInputAsDomainRoot(source,cmi)) {
            cmi.getDomainList().clear();
            Appserver70DomainNamesResolver as =new Appserver70DomainNamesResolver(source);
            domainMapping = as.getDomainNamesPathMapping();
            cmi.setInstallConfig70(as.getConfigDir70(source));
            cmi.setDomainMapping(domainMapping);
            Enumeration ee =  domainMapping.keys();
            while (ee.hasMoreElements()) {
                String domain = (String)ee.nextElement();
                cmi.addDomainName(domain);
                cmi.getTargetDomainNameMapping().put(domain,domain);
            }
        } else {     // Input source is domainRoot now
            File sourceDomain = new File(source);
            String [] dirs = sourceDomain.list();
            //sourceInputAsDomainRoot
            /*if(dirs.length == 0) {
                sourceInputAsDomainRoot = false;
                return sourceInputAsDomainRoot;
            }   */
            String domain = "";
            domainMapping = new Hashtable();
            for (int i=0;i<dirs.length;i++) {
                String domainPath=source + File.separator + dirs[i];
                File file = new File(domainPath);
                if(!(dirs[i].endsWith("8x")) && !(file.isFile()) && isValid70Domain(domainPath)) {
                    domain=dirs[i];
                    domainMapping.put(domain,new DomainInfo(domain,domainPath));
                    cmi.addDomainName(domain);
                    if(new File(cmi.getSourceDomainRoot()).equals(new File(cmi.getTargetDomainRoot())))
                        cmi.getTargetDomainNameMapping().put(domain,domain+"_8x");
                    else
                        cmi.getTargetDomainNameMapping().put(domain,domain);
                }
            }
        }
        System.setProperty("com.sun.aas.configRoot", cmi.getTargetInstallDir() + File.separator + "config");
        return domainMapping;
    }
    public Hashtable enlistDomainsFromDomainsDirectory(CommonInfoModel cmi, String domainsDirStr){
        File domainsDir = new File(domainsDirStr);
        String [] dirs = domainsDir.list();
        return enlistDomains(cmi,dirs, domainsDirStr);
    }
    
    public Hashtable enlistDomains(CommonInfoModel cmi, String [] dirs, String domainRoot) {
        Hashtable domainMapping = new Hashtable();
        boolean domainRootSame = new File(cmi.getSourceDomainRoot()).equals(new File(cmi.getTargetDomainRoot()));
        for (int i=0;i<dirs.length;i++) {
            if(dirs[i].equals("backup"))
                continue;
            String domainPath=domainRoot + File.separator + dirs[i];
            if(new File(domainPath+"_8x").exists())
                continue;
            File domainFile = new File(domainPath);
            if(domainFile.isFile())
                continue;
            if(domainRootSame) {
                //String latestdomain = findLatestDomainDir(cmi.getSourceDomainRoot(),null);
                String latestdomain = findLatestDomainDir(cmi.getSourceDomainRoot(),dirs[i]);
                String backupDomainVersion = "";
                String actualDomainVersion = "garbage";
                if(latestdomain != null)  {
                    backupDomainVersion = (new VersionExtracter(latestdomain,cmi)).getVersion();
                    String[] directories = new File(cmi.getSourceDomainRoot()).list();
                    String domainName = null;
                    for(int j =0;j<directories.length;j++) {
                        if(directories[j].equals("backup") || new File(cmi.getSourceDomainRoot() + File.separator + directories[j]).isFile())
                            continue;
                        else {
                            domainName = directories[j];
                            break;
                        }
                    }
                    //actualDomainVersion = (new VersionExtracter(cmi.getSourceDomainRoot() + File.separator + domainName,cmi)).getVersion();
                    actualDomainVersion = (new VersionExtracter(cmi.getSourceDomainRoot() + File.separator + dirs[i],cmi)).getVersion();
                }
                if(!actualDomainVersion.equals(cmi.getTargetVersionAndEdition()) && !actualDomainVersion.equals(backupDomainVersion)) {
                    String timestamp=""+System.currentTimeMillis();
                    String newDomainName = "";
                    String domainName = dirs[i];
                    if(dirs[i].endsWith("_8x")) {
                        newDomainName = dirs[i].substring(0,dirs[i].indexOf("_8x"))+"_"+timestamp;
                        domainName = dirs[i].substring(0,dirs[i].indexOf("_8x"));
                    } else {
                        newDomainName = domainName+"_"+timestamp;
                    }
                    String backup = cmi.getTargetDomainRoot()+File.separator+"backup";
                    File backupFile = new File(backup);
                    if(!(backupFile.isDirectory())) {
                        backupFile.delete();
                        backupFile.mkdir();
                    }
                    File domainDir = new File(domainPath);
                    String sourceDomainPath = backup+File.separator+newDomainName;
                    //This check will take care of all the domain ending with _8x
                    if(new File(domainPath+"_8x").exists()) {
                        new File(domainPath+"_8x").renameTo(new File(sourceDomainPath));
                        domainDir.delete();
                    } else
                        domainDir.renameTo(new File(sourceDomainPath));
                    domainMapping.put(domainName,new DomainInfo(domainName,sourceDomainPath));
                    cmi.addDomainName(domainName);
                    cmi.getTargetDomainNameMapping().put(domainName,domainName);
                } else {
                    String latestDomain = findLatestDomainDir(cmi.getTargetDomainRoot(),dirs[i]);
                    domainMapping.put(dirs[i],new DomainInfo(dirs[i],latestDomain));
                    cmi.addDomainName(dirs[i]);
                    cmi.getTargetDomainNameMapping().put(dirs[i],dirs[i]);
                }
            } else {
                domainMapping.put(dirs[i],new DomainInfo(dirs[i],domainPath));
                cmi.addDomainName(dirs[i]);
                cmi.getTargetDomainNameMapping().put(dirs[i],dirs[i]);
                /*if(new File(cmi.getSourceDomainRoot()).getPath().equals(new File(cmi.getTargetDomainRoot()).getPath()))
                    cmi.getTargetDomainNameMapping().put(dirs[i],dirs[i]+"_8x");
                else
                    cmi.getTargetDomainNameMapping().put(dirs[i],dirs[i]);   */
            }
        }
        return domainMapping;
    }
    public Hashtable enlistDomainsFromUserDefinedDirectories(List srcDomainDirs){
        Hashtable domainMapping = null;
        for(Iterator dIt = srcDomainDirs.iterator(); dIt.hasNext();){
            if(domainMapping == null) domainMapping = new Hashtable();
            String domainDirStr = (String)dIt.next();
            Hashtable dMaps = this.enlistDomainsFromDomainsDirectory(this.common, domainDirStr);
            if(dMaps != null){
                for(Enumeration domainsEnum = dMaps.keys();domainsEnum.hasMoreElements();){
                    String dName = (String)domainsEnum.nextElement();
                    domainMapping.put(dName, dMaps.get(dName));
                }
            }
        }
        return domainMapping;
    }
    public String findLatestDomainDir(String domainRoot,String domainName) {
        File backupDir = new File(domainRoot+File.separator+"backup");
        String lastestDomainPath=null;
        long latestTimestamp = 0;
        if(backupDir.isDirectory()) {
            String [] dirs = backupDir.list();
            for(int i=0;i<dirs.length;i++) {
                String time = dirs[i].substring(dirs[i].lastIndexOf("_")+1);
                if(domainName != null )
                    if(!(dirs[i].startsWith(domainName)))
                        continue;
                long timestamp = Long.parseLong(time);
                if(timestamp > latestTimestamp) {
                    latestTimestamp = timestamp;
                    lastestDomainPath = domainRoot+File.separator+"backup"+File.separator+dirs[i];
                }
            }
        }
        return  lastestDomainPath;
    }
    
    public boolean checkSourceInputAsDomain(){
        //this supports 8.x domains only
        //TODO 7.x support for single domains
        File domainXML = new File(common.getSourceInstallDir() + File.separator + "config" + File.separator + "domain.xml");
        if(domainXML.isFile()) {
            return true;
        }
        return false;
    }
    
    public boolean checkSourceInputAsDomainRoot(String source, CommonInfoModel cmi) {
        if (source == null) {
            return false;
        }
        File sourceDomain = new File(source);
        File biDir = new File(source+File.separator+"bin");
        //String osName = cmi.getOSName();
        //if(!biDir.isDirectory() && sourceDomain.isDirectory() && osName.startsWith("SunOS")) {
        if(!biDir.isDirectory() && sourceDomain.isDirectory()) {
            // Now check wheather it is a domainRoot
            //by checking the existence of domain/server1/config/server.xml file
            String [] dirs = sourceDomain.list();
            //sourceInputAsDomainRoot
            if(dirs.length == 0) {
                cmi.setSourceDomainRootFlag(false);
                return false;
            }
            
            if(new File(source + File.separator +"backup").exists()) {
                cmi.setSourceDomainRootFlag(true);
                return true;
            }
            // Checking If it contains 8.0 domain
            for (int i=0;i<dirs.length;i++) {
                File domainXML = new File(source+File.separator+dirs[i]+File.separator+"config"+File.separator+"domain.xml");
                if(domainXML.isFile()) {
                    cmi.setSourceDomainRootFlag(true);
                    return true;
                }
            }
            
            // Checking If it contains 7.0 domain
            //if(cmi.getSourceVersion().equals(UpgradeConstants.VERSION_7X)){
            // Get any 7.0 domain
            String domain = "";
            boolean domain70=false;
            for (int i=0;i<dirs.length;i++) {
                if(!(dirs[i].endsWith("8x")) && (new File(source +File.separator+ dirs[i]).isDirectory()) && this.isValid70Domain(source + File.separator + dirs[i])) {
                    domain = dirs[i];
                    domain70 =true;
                    break;
                }
            }
            if(!domain70)
                return false;
            File domainDir = new File(source+File.separator+domain);
            String [] serverDirs = domainDir.list();
            String serverInstanceName ="";
            if(serverDirs[0].equals("admin-server"))
                serverInstanceName = serverDirs[1];
            else
                serverInstanceName = serverDirs[0];
            File serverXML = new File(source+File.separator+domain+File.separator+serverInstanceName+File.separator+"config"+File.separator+"server.xml");
            if(serverXML.isFile())
                cmi.setSourceDomainRootFlag(true);
            else
                cmi.setSourceDomainRootFlag(false);
            /*}else {
                File domainXML = new File(source+File.separator+dirs[0]+File.separator+"config"+File.separator+"domain.xml");
                if(domainXML.isFile())
                    cmi.setSourceDomainRootFlag(true);
                else
                    cmi.setSourceDomainRootFlag(false);
            }  */
            
        }else {
            cmi.setSourceDomainRootFlag(false);
        }
        return cmi.getSourceDomainRootFlag();
    }
    public boolean isValid70Domain(String domainPath) {
        File domainDir = new File(domainPath);
        boolean domain70 = false;
        String [] serverDirs = domainDir.list();
        String serverInstanceName ="";
        if(serverDirs[0].equals("admin-server"))
            serverInstanceName = serverDirs[1];
        else
            serverInstanceName = serverDirs[0];
        File serverXML = new File(domainPath+File.separator+serverInstanceName+File.separator+"config"+File.separator+"server.xml");
        if(serverXML.isFile())
            domain70 = true;
        else
            domain70 = false;
        return domain70;
    }
    public String versionString(String versionEditionString){
        if(UpgradeConstants.VERSION_AS7X_PE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS7X_SE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS7X_EE.equals(versionEditionString)){
            return UpgradeConstants.VERSION_7X;
        }
        if(UpgradeConstants.VERSION_AS80_PE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS80_SE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS81_EE.equals(versionEditionString)){
            return UpgradeConstants.VERSION_80;
        }
        if(UpgradeConstants.VERSION_AS81_PE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS81_EE.equals(versionEditionString)){
            return UpgradeConstants.VERSION_81;
        }
        if(UpgradeConstants.VERSION_AS90_PE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS90_SE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS90_EE.equals(versionEditionString)){
            return UpgradeConstants.VERSION_90;
        }
        return "";
    }
    public String editionString(String versionEditionString){
        if(UpgradeConstants.VERSION_AS7X_PE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS80_PE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS81_PE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS90_PE.equals(versionEditionString)){
            return UpgradeConstants.EDITION_PE;
        }
        if(UpgradeConstants.VERSION_AS7X_SE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS80_SE.equals(versionEditionString)||
                UpgradeConstants.VERSION_AS90_SE.equals(versionEditionString)){
            return UpgradeConstants.EDITION_SE;
        }
        if(UpgradeConstants.VERSION_AS7X_EE.equals(versionEditionString) ||
                UpgradeConstants.VERSION_AS81_EE.equals(versionEditionString)||
                UpgradeConstants.VERSION_AS81_EE.equals(versionEditionString)||
                UpgradeConstants.VERSION_AS90_EE.equals(versionEditionString)){
            return UpgradeConstants.EDITION_EE;
        }
        return "";
    }
    public boolean isValidSourcePath(String sourcePath){
        File biDir = new File(sourcePath+File.separator+"bin");
        if(sourcePath.equals("") || !biDir.isDirectory()) {
            if(!checkSourceInputAsDomainRoot(sourcePath, common)) {
                //check for 8.x domain dir as input
                if(new File(sourcePath + File.separator + "config").isDirectory()){
                    return true;
                }
                return false;
            }
            common.setSourceDomainRoot(sourcePath);
        }
        // First check if it is regular 7.x install directory.
        String as7xInstallFileName = "admingui.ear"; //only exists in 7.x installations
        File runtime70Jar = new File(sourcePath+File.separator+"lib"+File.separator+as7xInstallFileName);
        if((runtime70Jar != null) && runtime70Jar.exists()) {
            // Its a valid 7.x directory.
            return true;
        }
        // Now check if it is AS8.x or solaris 10 installation or in-place upgrade.
        String[] domainConfigDirs = new VersionExtracter(sourcePath,common).getDomainAndConfigDirs();
        if(domainConfigDirs == null || domainConfigDirs.length == 0){
            // if sourcePath is not valid, then getDomainAndConfigDirs returns null;
            return false;
        }
        String domainsDir = domainConfigDirs[0];
        
        // If the domainsDir is <sourcePath>/domains then sourcePath is AS8.0.
        // If the domainsDir is <sourcePath>_bak then sourcePath is AS8.0 in-place upgrade. (in-place upgrade only supported from 8.0PE onwards
        // if the domainsDir is <sourcePath>  then sourcePath is a domains directory given for solaris 10 integration.
        if(domainsDir == null)
            return false;
        return true;
    }
    public boolean isValidTargetPath(String targetPath){
        
        /*
        String osName = System.getProperty("os.name");
        String asenv = null;
        String asadmin = null;
        if(osName.indexOf("Windows") != -1)
            asadmin = targetPath + File.separator + "bin" + File.separator + "asupgrade.bat";
        else
            asadmin = targetPath + File.separator + "bin" + File.separator + "asupgrade";
        try {
            if(! new File(asadmin).exists()) return false;
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(asadmin)));
            String readString =reader.readLine();
            while(readString != null) {
                if(readString.indexOf("targetVersion") != -1) {
                    return true;
                }
                readString =reader.readLine();
            }
        }catch (Exception e) {
            logger.log(Level.WARNING,this.stringManager.getString("enterprise.tools.upgrade.unknownError"),e);
        }*/
        
        if(!new File(targetPath).isDirectory())
            return false;
        
        return true;
    }
    public List getStandAloneInstances(Hashtable domainsMapping){
        // This method is called while upgradeing 7.x EE upgrading. This comapres with servers listed in clusters with domains mapping.
        List stdAloneList = new ArrayList();
        for(Iterator domIt=domainsMapping.values().iterator(); domIt.hasNext();){
            DomainInfo dInfo = (DomainInfo)domIt.next();
            for(Iterator instIt = dInfo.getInstanceNames().iterator(); instIt.hasNext();){
                String instName = (String)instIt.next();
                if(this.isInstanceInCluster(instName)){
                    continue;
                }
                if( !instName.equals("admin-server") ) {
                    Vector instDInfo = new Vector();
                    instDInfo.add(instName);
                    instDInfo.add(dInfo);
                    stdAloneList.add(instDInfo);
                }
            }
        }
        return stdAloneList;
    }
    public boolean isInstanceInCluster(String instName){
        // This method is a utility method to check for the instnce clustered or not.
        List clList = ClustersInfoManager.getClusterInfoManager().getClusterInfoList();
        if(clList == null) return false;
        for(Iterator clIt = clList.iterator(); clIt.hasNext(); ){
            ClusterInfo clInfo = (ClusterInfo)clIt.next();
            for(Iterator instIt = clInfo.getClusteredInstanceList().iterator(); instIt.hasNext();){
                if(((ClusteredInstance)instIt.next()).getInstanceName().equals(instName)){
                    return true;
                }
            }
        }
        return false;
    }
    private Element getConfigElementFromDocumentElement(Element documentElement, String lookUpConfigName){
        NodeList configEles = documentElement.getElementsByTagName("config");
        Element configEle = null;
        for(int lh =0; lh < configEles.getLength(); lh++){
            String configName = ((Element)configEles.item(lh)).getAttribute("name");
            if(configName.equals(lookUpConfigName)){
                configEle = (Element)configEles.item(lh);
                break;
            }
        }
        return configEle;
    }
    public boolean switchedIIOPPorts(String serverID, String portValue, Element documentElement){
        Element configEle = this.getConfigElementFromDocumentElement(documentElement, "server-config");
        NodeList iiopService = configEle.getElementsByTagName("iiop-service");
        NodeList iiopListeners = ((Element)iiopService.item(0)).getElementsByTagName("iiop-listener");
        Element iiopListener = null;
        for(int ii =0; ii < iiopListeners.getLength(); ii++){
            if(((Element)iiopListeners.item(ii)).getAttribute("id").equals("orb-listener-1")){
                iiopListener = (Element)iiopListeners.item(ii);
                break;
            }
        }
        if(iiopListener != null){
            String serverIIOPPort = this.getIIOPListenerPortForServer(iiopListener.getAttribute("port"), "server", documentElement);
            if(serverIIOPPort.equals("3700")){
                String portValueFromServer = this.getIIOPListenerPortForServer(portValue,serverID, documentElement);
                if(portValueFromServer != null)
                    iiopListener.setAttribute("port", portValueFromServer);
                return true;
            }else{
                return false;
            }
        }
        return false;
    }
    private String getIIOPListenerPortForServer(String portValue, String serverName, Element documentElement){
        try{
            if(portValue != null){
                int portIntValue = Integer.parseInt(portValue);
                return String.valueOf(portIntValue);
            }
        }catch(java.lang.NumberFormatException ne){
            // This shows the the portValue is not a string but ${IIOP_LISTENER_PORT}
        }
        NodeList servers = documentElement.getElementsByTagName("servers");
        NodeList serverList = ((Element)servers.item(0)).getElementsByTagName("server");
        String portValueFromServer = null;
        for(int lh =0; lh < serverList.getLength(); lh++){
            if(serverName.equals(((Element)serverList.item(lh)).getAttribute("name"))){
                Element serverElement = (Element)serverList.item(lh);
                Element sysProp = getSystemPropertyElement("IIOP_LISTENER_PORT",serverElement);
                if(sysProp != null){
                    return sysProp.getAttribute("value");
                }else{
                    Element configElement = this.getConfigElementFromDocumentElement(documentElement, serverElement.getAttribute("config-ref"));
                    if(configElement != null){
                        sysProp = getSystemPropertyElement("IIOP_LISTENER_PORT",configElement);
                        if(sysProp != null)
                            return sysProp.getAttribute("value");
                    }
                }
            }
        }
        return null;
    }
    private Element getSystemPropertyElement(String propertyName, Element parentForSysProp){
        NodeList sysProps = parentForSysProp.getElementsByTagName("system-property");
        for(int sh =0; sh < sysProps.getLength(); sh++){
            if(propertyName.equals(((Element)sysProps.item(sh)).getAttribute("name"))){
                return ((Element)sysProps.item(sh));
            }
        }
        return null;
    }
    public void updateDomainXMLWithIIOPCluster(CommonInfoModel cmnInfo, String domainXMLFile, IIOPCluster iiopCluster){
        String clusterName = iiopCluster.getClusterName();
        List servInstances = iiopCluster.getIIOPServerInstanceList();
        boolean domainFileChanged = false;
        Document domainDoc = this.getDomainDocumentElement(domainXMLFile);
        for(int servIt = 0; servIt < servInstances.size(); servIt++){
            List endPoints = ((IIOPServerInstance)servInstances.get(servIt)).getIIOPEndPoints();
            String serverName = ((IIOPServerInstance)servInstances.get(servIt)).getName();
            for(int endPt = 0; endPt < endPoints.size(); endPt++){
                IIOPEndPoint iiopEndPoint = (IIOPEndPoint)endPoints.get(endPt);
                // just use only one endpoint and transfer the port no.
                if(domainDoc != null){
                    String propertyName = "IIOP_LISTENER_PORT";
                    String propValue = iiopEndPoint.getPort();
                    NodeList servers = domainDoc.getDocumentElement().getElementsByTagName("servers");
                    NodeList serverList = ((Element)servers.item(0)).getElementsByTagName("server");
                    if(propValue.equals("3700")){
                        this.switchedIIOPPorts(serverName, null, domainDoc.getDocumentElement());
                        //logger.log(Level.WARNING,this.stringManager.getString("enterprise.tools.upgrade.iiop_port_defined"));
                    }
                    // Passing baseElement as null.  "IIOP_LISTENER_PORT" should definitely exist.  Ssome times the create-instance does not add it.
                    // This base element is only a structural reference to invoke appendChild method.
                    BaseElement baseElement = null;
                    try{
                        baseElement = com.sun.enterprise.tools.upgrade.transform.ElementToObjectMapper.getMapper().getElementObject(domainDoc.getDocumentElement().getTagName());
                    }catch(Exception ef){
                    }
                    this.addOrUpdateSystemPropertyToServer(serverName,serverList, propertyName, propValue, baseElement);
                    domainFileChanged = true;
                }
                break;
            }
        }
        if(domainFileChanged && (domainDoc != null)){
            this.saveDocumentToDomainFile(domainXMLFile, domainDoc);
        }
    }
    public java.util.List updateClusterList(String domainXMLFile, String domainName, java.util.List clList){
        Document domainDoc = this.getDomainDocumentElement(domainXMLFile);
        if(domainDoc != null){
            NodeList clusters = domainDoc.getDocumentElement().getElementsByTagName("clusters");
            if(clusters != null){
                NodeList clusterList = ((Element)clusters.item(0)).getElementsByTagName("cluster");
                if((clusterList != null) && (clusterList.getLength() >0)){
                    for(int lh =0; lh < clusterList.getLength(); lh++){
                        String clName = ((Element)clusterList.item(lh)).getAttribute("name");
                        ClusterInfo clInfo = new ClusterInfo();
                        clInfo.setClusterName(clName);
                        clInfo.setDomainName(domainName);
                        clList.add(clInfo);
                    }
                }
            }
        }
        return clList;
    }
    private Document getDomainDocumentElement(String domainFileName){
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //factory.setValidating(true);
        factory.setNamespaceAware(true);
        Document resultDoc = null;
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver((org.xml.sax.helpers.DefaultHandler)Class.forName
                    ("com.sun.enterprise.config.serverbeans.ServerValidationHandler").newInstance());
            resultDoc = builder.parse( new File(domainFileName));
        }catch (Exception ex){
            logger.log(Level.WARNING, stringManager.getString("enterprise.tools.upgrade.iiop_port_domain_doc"),ex);
        }
        return resultDoc;
    }
    private void saveDocumentToDomainFile(String domainFileName, Document resultDoc){
        // Use a Transformer for output
        try{
            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("enterprise.tools.upgrade.iiop_port_domain_save_fail"),ex);
            //throw new HarnessException(stringManager.getString("upgrade.transform.startFailureMessage"));
        }
    }
    
    public void recover() {
        List domainList = common.getDomainList();
        String sourceDir = common.getSourceDomainRoot();
        String targetDir = common.getTargetDomainRoot();
        if(domainList != null && sourceDir != null && targetDir != null) {
            Iterator itr = domainList.iterator();
            while(itr.hasNext()) {
                String dname = (String)itr.next();               
                boolean domainRootSame = new File(sourceDir).equals(new File(targetDir));               
                if(domainRootSame) {
                    if(new File(sourceDir + File.separator + "backup").isDirectory()) {                       
                        common.setCurrentDomain(dname);
                        String latestDomainPath=common.findLatestDomainDir(sourceDir);  
                        if(latestDomainPath != null) {
                            new File(latestDomainPath).renameTo(new File(sourceDir + File.separator + dname));
                            File backupdir = new File(sourceDir + File.separator + "backup");
                            String[] dirs = backupdir.list();
                            if(dirs.length == 0)
                                backupdir.delete();
                        }
                    }
                }
                
            }//while loop
        }//not null check of domainList
    }
    
    public boolean validateUserDetails(String adminUserName, String adminPassword, String masterPassword){
        try{
            com.sun.enterprise.admin.servermgmt.RepositoryManager rManager = new com.sun.enterprise.admin.servermgmt.RepositoryManager();
            String domainPath = this.common.getTargetDomainRoot();
            if(!new File(domainPath+File.separator+"domain1").exists() ||
                    ((common.getSourceInstallDir() != null && common.getTargetInstallDir() != null) && (common.getSourceInstallDir().equalsIgnoreCase(common.getTargetInstallDir() + File.separator + "domains") || (common.getSourceInstallDir().equalsIgnoreCase(common.getTargetInstallDir()))))){
                // domain1 should exist in target directory in order to validate user name and password.
                // If this does not exist, then cannot validate user name and password.  Just return true.
                // In case of in-place upgrade domain1 is created by upgrade process.  The time this method is called for user details validation
                // the domain1 wouldnt have been created.  Also, in case if in-place upgrade upgrade is invoked soon after installation.
                // The upgrade tool uses com.sun.enterprise.admin.servermgmt.RepositoryConfig to validate passwords before the upgrade starts.
                // The RepositoryConfig.validateAdminUserAndPassword() method doesn't work if an 8.1 domain hasn't been created.
                // In the in-place upgrade scenario the installer doesn't create one and this method gets called before the upgrade tool
                // creates one. When the upgrade tool does create a domain, it uses the passwords passed in by the installers to create the
                // new domains, so we don't have to worry about checking for incorrect passwords in this case.
                return true;
            }
            com.sun.enterprise.admin.servermgmt.RepositoryConfig repConf = new com.sun.enterprise.admin.servermgmt.RepositoryConfig("domain1",domainPath);
            rManager.validateAdminUserAndPassword(repConf,adminUserName,adminPassword);
            if((masterPassword != null) && (!this.common.getTargetVersionAndEdition().equals(UpgradeConstants.VERSION_AS81_PE)))
                rManager.validateMasterPassword(repConf,masterPassword);
        }catch(com.sun.enterprise.admin.servermgmt.RepositoryException re){
            logger.log(Level.SEVERE, stringManager.getString("enterprise.tools.upgrade.generalException", re.getMessage()), re);
            return false;
        }
        return true;
    }
    public void updateDomainXMLWithPersistenceStoreProps(java.util.Properties props){
        // TODO
        // Read each property and add it to appropriate place in domain.xml
        // Yet to hear back from Larry white.
    }
    public void updateListenerPortsForClusteredInstances(Element docElement, String propertyName, String portValue, BaseElement bElement){
        NodeList servers = docElement.getElementsByTagName("servers");
        NodeList serverList = ((Element)servers.item(0)).getElementsByTagName("server");
        String clusterName = this.common.getCurrentCluster();
        for(java.util.Iterator dItr = ClustersInfoManager.getClusterInfoManager().getClusterInfoList().iterator(); dItr.hasNext();){
            ClusterInfo cInfo = (ClusterInfo)dItr.next();
            if(cInfo.getClusterName().equals(clusterName)){
                for(java.util.Iterator clItr = cInfo.getClusteredInstanceList().iterator(); clItr.hasNext();){
                    ClusteredInstance clInstance = (ClusteredInstance)clItr.next();
                    if(portValue == null){
                        this.addOrUpdateSystemPropertyToServer(clInstance.getInstanceName(), serverList, propertyName, clInstance.getInstancePort(),bElement);
                    }else{
                        this.addOrUpdateSystemPropertyToServer(clInstance.getInstanceName(), serverList, propertyName, portValue,bElement);
                    }
                }
            }
        }
    }
    public void addOrUpdateSystemPropertyToServer(String serverName, NodeList serverList, String propertyName, String propertyValue, BaseElement bElement){
        for(int lh =0; lh < serverList.getLength(); lh++){
            if(serverName.equals(((Element)serverList.item(lh)).getAttribute("name"))){
                Element serverElement = (Element)serverList.item(lh);
                Element sysProp = this.getSystemPropertyElement(propertyName,serverElement);
                if(sysProp != null){
                    sysProp.setAttribute("value", propertyValue);
                    return;
                }
                if(sysProp == null){
                    // bElement could be passed as null in case if this property need not be added.
                    if(bElement != null){
                        sysProp = serverElement.getOwnerDocument().createElement("system-property");
                        sysProp.setAttribute("name", propertyName);
                        sysProp.setAttribute("value", propertyValue);
                        bElement.appendElementToParent(serverElement,sysProp);
                    }
                }
                return;
            }
        }
    }
    
    public void copyFile(String source, String target) throws IOException {
        copyFile(source, target, false);
    }
    
    public void copyFile(String source, String target, boolean append) throws IOException{
        //copy the file
        //FileReader in = new FileReader(new File(source));
        //FileWriter out = new FileWriter(new File(target), append);
        //FileReader/FileWriter were corrupting keystore files.
        FileInputStream in = new FileInputStream(new File(source));
        FileOutputStream out = new FileOutputStream(new File(target), append);
        int c;
        while ((c = in.read()) != -1) {
            out.write(c);
        }
        in.close();
        out.close();
    }
    
    //returns the value of the jvm-option or null if not found
    public String getJvmOptionValueFromSourceConfig(String optionName) {
        String sourceConfig = common.getSourceConfigXMLFile();
        Document sourceDoc = this.getDomainDocumentElement(common.getSourceConfigXMLFile());
        NodeList serverList = sourceDoc.getElementsByTagName("server");
        String serverName = common.getCurrentSourceInstance();
        if (serverName == null || serverName == "") {
            serverName = "server";
        }
        String configName = null;
        String password = null;
        for(int i=0;i<serverList.getLength();i++){
            Node serverNode = (Node)serverList.item(i);
            NamedNodeMap attributes = serverNode.getAttributes();
            String name = (attributes.getNamedItem("name")).getNodeValue();
            if(serverName.equals(name)){
                configName = (attributes.getNamedItem("config-ref")).getNodeValue();
            }
        }
        if (configName != null) {
            NodeList jvmOptionList = sourceDoc.getElementsByTagName("jvm-options");
            for(int j=0;j<jvmOptionList.getLength();j++) {
                Node jvmNode = jvmOptionList.item(j);
                String jvmOptions = getTextNodeData((Element)jvmNode);
                if (jvmOptions.indexOf(optionName) != -1) {
                    password = jvmOptions.substring(jvmOptions.indexOf("=")+1, jvmOptions.length());
                }
            }
        } else {
            logger.warning(stringManager.getString("enterprise.tools.upgrade.configNotFound", configName));
        }
        return password;
        
    }
    
    public String getTextNodeData(Element element){
        NodeList children = element.getChildNodes();
        for(int index=0; index < children.getLength(); index++){
            if(children.item(index).getNodeType() == Node.TEXT_NODE){
                return children.item(index).getNodeValue();
            }
        }
        return "";
    }
}
