All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jbi.management.system.AutoAdminTask Maven / Gradle / Ivy

Go to download

JBI Runtime Management components, providing installation, deployment, and other JMX interfaces for remote management consoles.

There is a newer version: 2.4.3
Show newest version
/*
 * BEGIN_HEADER - DO NOT EDIT
 *
 * 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://open-esb.dev.java.net/public/CDDLv1.0.html.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * HEADER in each file and include the License file at
 * https://open-esb.dev.java.net/public/CDDLv1.0.html.
 * If applicable add the following below this CDDL HEADER,
 * with the fields enclosed by brackets "[]" replaced with
 * your own identifying information: Portions Copyright
 * [year] [name of copyright owner]
 */

/*
 * @(#)AutoAdminTask.java
 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
 *
 * END_HEADER - DO NOT EDIT
 */
package com.sun.jbi.management.system;

import com.sun.jbi.JBIProvider;
import com.sun.jbi.StringTranslator;
import com.sun.jbi.management.config.DeploymentConfigurationFactory;
import com.sun.jbi.management.config.InstallationConfigurationFactory;
import com.sun.jbi.management.LocalStringKeys;
import com.sun.jbi.management.MBeanNames;
import com.sun.jbi.management.repository.Archive;
import com.sun.jbi.management.repository.ArchiveType;
import com.sun.jbi.ui.common.JBIManagementMessage;
//import com.sun.org.apache.xpath.internal.XPathAPI;
import java.io.File;
import java.io.FilenameFilter;
import java.io.FileOutputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jbi.management.DeploymentServiceMBean;
import javax.management.ObjectName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;

/**
 * This is the JBI Framework Auto Admin Task, which helps with autodeploy and
 * autoinstall functionality.
 *
 * @author Sun Microsystems, Inc.
 */
public class AutoAdminTask
{
    /** Root directory for autoinstall. */
    public static final String AUTOINSTALL_DIR = "autoinstall";

    /** Working directory for installer. */
    private static final String INSTALL_STATUS_DIR = ".autoinstallstatus";

    /** File name suffix for a successful autoinstall operation. */
    private static final String INSTALL_SUCCESS = "_installed";

    /** File name suffix for an unsuccessful autoinstall operation. */
    private static final String INSTALL_FAILURE = "_notInstalled";    

    /** File name suffix for a successful autouninstall operation. */
    private static final String UNINSTALL_SUCCESS = "_uninstalled";

    /** File name suffix for an unsuccessful autouninstall operation. */
    private static final String UNINSTALL_FAILURE = "_notUninstalled";    

    /** Root directory for autodeploy. */
    public static final String AUTODEPLOY_DIR = "autodeploy";

    /** Working directory for deployer. */
    private static final String DEPLOY_STATUS_DIR = ".autodeploystatus";

    /** File name suffix for a successful autodeploy operation. */
    private static final String DEPLOY_SUCCESS = "_deployed";

    /** File name suffix for an unsuccessful autodeploy operation. */
    private static final String DEPLOY_FAILURE = "_notDeployed";    

    /** File name suffix for a successful autoundeploy operation. */
    private static final String UNDEPLOY_SUCCESS = "_undeployed";

    /** File name suffix for an unsuccessful autoundeploy operation. */
    private static final String UNDEPLOY_FAILURE = "_notUndeployed";    

    /** Separates the autodeployed file's name from the SA name */
    public static final String DELIMITER = "--";

    /** Separates the autoinstalled file's name from the component's name */
    public static final String COMP_DELIMITER = DELIMITER + "comp" + DELIMITER;

    /** Separates the autoinstalled file's name from the shared library's name */
    public static final String SL_DELIMITER = DELIMITER + "sl" + DELIMITER;

    /**
     * Management context
     */
    private ManagementContext mContext;

    //where to log messages:
    private Logger mLogger;

    // Directory from where JBI picks up installable jars
    private File mAutoInstallDir;
    private String mAutoInstallDirName;

    // Directory from where JBI picks up deployable zips
    private File mAutoDeployDir;
    private String mAutoDeployDirName;

    // Work directory for installation (where timestamps and associations are kept)
    private File mInstallTimestampsDir;

    // Work directory for deployment (where timestamps and associations are kept)
    private File mDeployTimestampsDir;

    //DocumentBuilder
    private DocumentBuilder mDocBuilder;

    /** is auto install currently enabled? */
    private boolean mAutoInstallEnabled;

    /** is auto reinstall currently enabled? */
    private boolean mAutoReinstallEnabled;

    /** is auto uninstall currently enabled? */
    private boolean mAutoUninstallEnabled;

    /** is auto deploy currently enabled? */
    private boolean mAutoDeployEnabled = false;  // always false for Glassfish

    /** is auto redeploy currently enabled? */
    private boolean mAutoRedeployEnabled;

    /** is auto undeploy currently enabled? */
    private boolean mAutoUndeployEnabled;

    /** ObjectName for InstallationService */
    private ObjectName mInstallationMBean;

    /** ObjectName for DeploymentService */
    private ObjectName mDeploymentMBean;

    /** ObjectName for Installation ConfigurationService */
    private ObjectName mInstallConfigSvcMBean;

    /** ObjectName for Deployment ConfigurationService */
    private ObjectName mDeployConfigSvcMBean;

    /** 
     * Handle to StringTranslator for message translation
     */  
    private StringTranslator mTranslator;

    /**
     * The three different types of query for the pollAutoDirectory function
     */
    public enum PollFunction
    {
        NEW_FILES,
        DELETED_FILES,
        UPDATED_FILES
    }

    /**
     * Filters out all status files except for those starting with the given prefix.
     */
    private class NamedFileFinder implements FilenameFilter {
        String prefix = null;
        NamedFileFinder(String p) {
            prefix = p;
        }
        public boolean accept(File dir, String name) {
            if (name.startsWith(prefix + DELIMITER)) {
                return true;
            }
            return false;
        }
    }

    /**
     * Constructs a AutoAdminTask.
     * @param anEnv is the ManagementContext.
     */
    public AutoAdminTask (ManagementContext anEnv)
    {
        mContext = anEnv;
        mLogger = mContext.getLogger();
        mTranslator = (StringTranslator) anEnv.getEnvironmentContext().
                getStringTranslator("com.sun.jbi.management");
        
        // Autoinstall and Autodeploy always target the local instance
        mInstallationMBean = mContext.getMBeanNames().getSystemServiceMBeanName(
                MBeanNames.ServiceName.InstallationService,
                MBeanNames.ServiceType.Installation,
                mContext.getEnvironmentContext().getPlatformContext().getInstanceName());

        mDeploymentMBean = mContext.getMBeanNames().getSystemServiceMBeanName(
                MBeanNames.ServiceName.DeploymentService,
                MBeanNames.ServiceType.Deployment,
                mContext.getEnvironmentContext().getPlatformContext().getInstanceName());

        mInstallConfigSvcMBean = mContext.getMBeanNames().getSystemServiceMBeanName(
                MBeanNames.ServiceName.ConfigurationService,
                MBeanNames.ServiceType.Installation,
                mContext.getEnvironmentContext().getPlatformContext().getInstanceName());

        mDeployConfigSvcMBean = mContext.getMBeanNames().getSystemServiceMBeanName(
                MBeanNames.ServiceName.ConfigurationService,
                MBeanNames.ServiceType.Deployment,
                mContext.getEnvironmentContext().getPlatformContext().getInstanceName());

    }

    /**
     * Constructs a AutoAdminTask for use by junit tests.
     * @param anEnv is the ManagementContext.
     * @param autoInstallDir Directory for auto install dir
     * @param autoDeployDir Directory for auto deploy dir
     * @param isAutoInstallEnabled true iff the auto install permission bit set.
     * @param isAutoDeployEnabled true iff the auto deploy permission bit set.
     */
    public AutoAdminTask (ManagementContext anEnv,
                          String            aDirectoryForAutoInstall,
                          String            aDirectoryForAutoDeploy,
                          boolean           isAutoInstallEnabled,
                          boolean           isAutoDeployEnabled)
    {
        this(anEnv);
        mAutoInstallDirName = aDirectoryForAutoInstall;
        mAutoDeployDirName = aDirectoryForAutoDeploy;
        mAutoInstallEnabled = isAutoInstallEnabled;
        mAutoReinstallEnabled = isAutoInstallEnabled;
        mAutoUninstallEnabled = isAutoInstallEnabled;
        mAutoDeployEnabled = isAutoDeployEnabled;
        mAutoRedeployEnabled = isAutoDeployEnabled;
        mAutoUndeployEnabled = isAutoDeployEnabled;
    }   
            
    /**
     * Process autoinstall and autodeploy directories.
     * @throws Exception unexpectedly.
     */
    public synchronized void performAutoFunctions()
        throws Exception
    {
        // for efficiency, check configuration settings once per heartbeat

        mAutoInstallDirName = getConfigAttribute(mInstallConfigSvcMBean,
                             InstallationConfigurationFactory.AUTO_INSTALL_DIR);
        mAutoDeployDirName = getConfigAttribute(mDeployConfigSvcMBean,
                                DeploymentConfigurationFactory.AUTO_DEPLOY_DIR);
        mAutoInstallEnabled = checkConfigPermission(mInstallConfigSvcMBean,
                          InstallationConfigurationFactory.ENABLE_AUTO_INSTALL);
        mAutoReinstallEnabled = checkConfigPermission(mInstallConfigSvcMBean,
                        InstallationConfigurationFactory.ENABLE_AUTO_REINSTALL);
        mAutoUninstallEnabled = checkConfigPermission(mInstallConfigSvcMBean,
                        InstallationConfigurationFactory.ENABLE_AUTO_UNINSTALL);
        // Glassfish handles autodeploy on its own
        if (mContext.getEnvironmentContext().getProvider() != JBIProvider.SUNAS)
        {
            mAutoDeployEnabled = checkConfigPermission(mDeployConfigSvcMBean,
                             DeploymentConfigurationFactory.ENABLE_AUTO_DEPLOY);
            mAutoRedeployEnabled = checkConfigPermission(mDeployConfigSvcMBean,
                           DeploymentConfigurationFactory.ENABLE_AUTO_REDEPLOY);
            mAutoUndeployEnabled = checkConfigPermission(mDeployConfigSvcMBean,
                           DeploymentConfigurationFactory.ENABLE_AUTO_UNDEPLOY);
        }

        initDirectories(mAutoInstallEnabled, mAutoDeployEnabled);

        if (mAutoInstallEnabled)
        {
            performAutoInstall();
            // only perform autouninstall if autoinstall is also enabled
            if (mAutoUninstallEnabled)
            {
                performAutoUninstall();
                // only perform autoreinstall if autoinstall and autouninstall
                // are also enabled
                if (mAutoUninstallEnabled)
                {
                    performAutoReinstall();
                }
            }
        }

        if (mAutoDeployEnabled)
        {
            performAutoDeploy();
            // only perform autoundeploy if autodeploy is also enabled
            if (mAutoUndeployEnabled)
            {
                performAutoUndeploy();
                // only perform autoredeploy if autodeploy and autoundeploy
                // are also enabled
                if (mAutoRedeployEnabled)
                {
                    performAutoRedeploy();
                }
            }
        }
    }


    /**
     * Process autoinstall directory for new files.
     * @throws Exception unexpectedly.
     */
    public void performAutoInstall()
    {
        File    installFile;
        while ((installFile =
            pollAutoDirectory(PollFunction.NEW_FILES,
                              mAutoInstallDir, mInstallTimestampsDir)) != null)
        {
            doInstall(installFile);
        }
    }

    /**
     * Routine called by both performAutoInstall() and performAutoReinstall()
     * to do the installation of a specific component file.
     * @param installFile the File to install.
     */
    private void doInstall(File installFile)
    {
        Archive installArchive;
        String  componentName;
        
        try
        {
            // create timestamp for this file -- copy time from existing one
            String fileName = installFile.getName();
            File timeStamp = new File(mInstallTimestampsDir, fileName);
            timeStamp.createNewFile();
            timeStamp.setLastModified(installFile.lastModified());

            installArchive = new Archive(installFile, true);
            if (installArchive.getType().equals(ArchiveType.COMPONENT))
            {
                componentName = installComponent(installFile.getAbsolutePath());
                // store the name in an empty file
                File storedNameFile = new File (mInstallTimestampsDir,
                    fileName + COMP_DELIMITER + componentName);
                if (null != componentName)
                {
                    storedNameFile.createNewFile();
                    storedNameFile.setLastModified(installFile.lastModified());
                }
            }
            else if (installArchive.getType().equals(ArchiveType.SHARED_LIBRARY))
            {
                componentName = installSharedLibrary(installFile.getAbsolutePath());
                // store the name in an empty file
                File storedNameFile = new File (mInstallTimestampsDir,
                    fileName + SL_DELIMITER + componentName);
                if (null != componentName)
                {
                    storedNameFile.createNewFile();
                    storedNameFile.setLastModified(installFile.lastModified());
                }
            }
            else if (installArchive.getType().equals(ArchiveType.SERVICE_ASSEMBLY))
            {
                removeInstallLogs(installFile.getAbsolutePath());
                writeLog(installFile.getAbsolutePath() + INSTALL_FAILURE, 
                        mTranslator.getString(LocalStringKeys.AA_DEPLOY_NOT_SUPPORTED));
            }
        }
        catch (Exception ex)
        {
            removeInstallLogs(installFile.getAbsolutePath());
            writeLog(installFile.getAbsolutePath() + INSTALL_FAILURE, ex.toString());
        }
    }

    /**
     * Process autodeploy directory for new files.
     * @throws Exception unexpectedly.
     */
    public void performAutoDeploy()
    {
        File    deployFile;

        while ((deployFile =
            pollAutoDirectory(PollFunction.NEW_FILES,
                              mAutoDeployDir, mDeployTimestampsDir)) != null)
        {
            doDeploy(deployFile);
        }
    }

    /**
     * Routine called by both performAutoDeploy() and performAutoRedeploy()
     * to do the deployment of a specific service assembly
     * @param deployFile the File to install.
     */
    private void doDeploy(File deployFile)
    {
        Archive deployArchive;
        String  componentName;
        
        try
        {
            // create timestamp for this file -- copy time from existing one
            String fileName = deployFile.getName();
            File timeStamp = new File(mDeployTimestampsDir, fileName);
            timeStamp.createNewFile();
            timeStamp.setLastModified(deployFile.lastModified());

            deployArchive = new Archive(deployFile, true);
            if (deployArchive.getType().equals(ArchiveType.SERVICE_ASSEMBLY))
            {
                String serviceAssemblyName = deployArchive.getJbiName();
                deployServiceAssembly(serviceAssemblyName,
                                      deployFile.getAbsolutePath());
                // store the name in an empty file
                File storedNameFile = new File (mDeployTimestampsDir,
                    fileName + DELIMITER + serviceAssemblyName);
                if (null != storedNameFile)
                {
                    storedNameFile.createNewFile();
                    storedNameFile.setLastModified(deployFile.lastModified());
                }
                
            }
            else
            {
                removeDeployLogs(deployFile.getAbsolutePath());
                writeLog(deployFile.getAbsolutePath() + DEPLOY_FAILURE, 
                        mTranslator.getString(LocalStringKeys.AA_INSTALL_NOT_SUPPORTED));
            }
        }
        catch (Exception ex)
        {
            removeDeployLogs(deployFile.getAbsolutePath());
            writeLog(deployFile.getAbsolutePath() + DEPLOY_FAILURE, ex.toString());
        }
    }

    /**
     * Process autoinstall directory for deleted files.
     * @throws Exception unexpectedly.
     */
    public void performAutoUninstall()
    {
        File    deletedFile;
        
        while ((deletedFile =
            pollAutoDirectory(PollFunction.DELETED_FILES,
                              mAutoInstallDir, mInstallTimestampsDir)) != null)
        {
            doUninstall(deletedFile);
        }
    }

    /**
     * Routine called by both performAutoUninstall() and performAutoReinstall()
     * to do the uninstallation of a specific component file.
     * @param deletedFile the File to uninstall.
     * @returns true iff the uninstall was successful.
     */
    private boolean doUninstall(File deletedFile)
    {
        String  fileName = null;
        
        try
        {
            // delete timestamp for this file
            fileName = deletedFile.getName();
            mLogger.log(Level.FINER, "doUninstall() deleting file {0}", fileName);
            deletedFile.delete();

            // find the file (if present) that specified if this was a
            //  shared library or component, and what its name was.
            for (File deletedData : mInstallTimestampsDir.listFiles(
                                        new NamedFileFinder(fileName)))
            {
                deletedData.delete();
                mLogger.log(Level.FINER, "doUninstall() on {0}", deletedData.getName());
                String cSuffix = suffix(deletedData.getName(), fileName + COMP_DELIMITER);
                String slSuffix = suffix(deletedData.getName(), fileName + SL_DELIMITER);
                if (null != cSuffix)
                {
                    uninstallComponent(cSuffix);
                }
                if (null != slSuffix)
                {
                    uninstallSharedLibrary(slSuffix);
                }
            }
            // put new log file in mAutoInstallDir, not timestamp dir.
            fileName = mAutoInstallDir.getAbsolutePath() + File.separator + fileName;
            removeInstallLogs(fileName);
            writeLog(fileName + UNINSTALL_SUCCESS, "");
            return true;
        }
        catch (Exception ex)
        {
            if (null != fileName)
            {
                // put new log file in mAutoInstallDir, not timestamp dir.
                fileName = mAutoInstallDir.getAbsolutePath() +
                           File.separator + fileName;
                removeInstallLogs(fileName);
                writeLog(fileName + UNINSTALL_FAILURE, ex.toString());
            }
            return false;
        }
    }

    /**
     * Process autodeploy directory for deleted files.
     * @throws Exception unexpectedly.
     */
    public void performAutoUndeploy()
    {
        File    deletedFile;
        
        while ((deletedFile =
            pollAutoDirectory(PollFunction.DELETED_FILES,
                              mAutoDeployDir, mDeployTimestampsDir)) != null)
        {
            doUndeploy(deletedFile);
        }
    }

    /**
     * Routine called by both performAutoUndeploy() and performAutoRedeploy()
     * to do the undeployment of a specific service assembly.
     * @param deletedFile the File to undeploy.
     * @returns true iff the undeploy was successful.
     */
    private boolean doUndeploy(File deletedFile)
    {
        String  fileName = null;
        boolean results = true;
        
        try
        {
            // delete timestamp for this file
            fileName = deletedFile.getName();
            mLogger.log(Level.FINER, "doUndeploy() deleting file {0}", fileName);
            deletedFile.delete();

            // find the file (if present) that specified
            // the name of the deployed service assembly.
            for (File deletedData : mDeployTimestampsDir.listFiles(
                                        new NamedFileFinder(fileName)))
            {
                deletedData.delete();
                mLogger.log(Level.FINER, "doUndeploy() on {0}", deletedData.getName());
                String saName = suffix(deletedData.getName(), fileName + DELIMITER);
                if (null != saName)
                {
                    results = undeployServiceAssembly(saName);
                }
            }
            // put new log file in mAutoDeployDir, not timestamp dir.
            fileName = mAutoDeployDir.getAbsolutePath() + File.separator + fileName;
            removeDeployLogs(fileName);
            writeLog(fileName + UNDEPLOY_SUCCESS, "");
            return results;
        }
        catch (Exception ex)
        {
            if (null != fileName)
            {
                // put new log file in mAutoDeployDir, not timestamp dir.
                fileName = mAutoDeployDir.getAbsolutePath() +
                           File.separator + fileName;
                removeDeployLogs(fileName);
                writeLog(fileName + UNDEPLOY_FAILURE, ex.toString());
            }
            return false;
        }
    }

    /**
     * Process autoinstall directory for updated files.
     * @throws java.io.IOException unexpectedly.
     */
    public void performAutoReinstall()
        throws java.io.IOException
    {
        File    updatedFile;
        
        while ((updatedFile =
            pollAutoDirectory(PollFunction.UPDATED_FILES,
                              mAutoInstallDir, mInstallTimestampsDir)) != null)
        {
            String fileName = updatedFile.getName();
            File timeStamp = new File(mInstallTimestampsDir, fileName);

            if (doUninstall(timeStamp))
            {
                doInstall(updatedFile);
            }
            else
            {
                // change the timestamp of our status file so that we do not
                // try to install the new version of the file
                timeStamp.createNewFile();  // it was deleted by doUninstall().
                timeStamp.setLastModified(updatedFile.lastModified());
            }
        }
    }

    /**
     * Process autodeploy directory for updated files.
     * @throws java.io.IOException unexpectedly.
     */
    public void performAutoRedeploy()
        throws java.io.IOException
    {
        File    updatedFile;
        
        while ((updatedFile =
            pollAutoDirectory(PollFunction.UPDATED_FILES,
                              mAutoDeployDir, mDeployTimestampsDir)) != null)
        {
            String fileName = updatedFile.getName();
            File timeStamp = new File(mDeployTimestampsDir, fileName);

            if (doUndeploy(timeStamp))
            {
                doDeploy(updatedFile);
            }
            else
            {
                // change the timestamp of our status file so that we do not
                // try to deploy the new version of the file
                timeStamp.createNewFile();  // it was deleted by doUndeploy().
                timeStamp.setLastModified(updatedFile.lastModified());
            }
        }
    }

    /**
     * Routine to parse the result of an install or deploy operation.
     * @param aResultString the task result result to parse.
     * @return true iff the task was executed successfully.
     *
     */
    private boolean parseResultAsSuccess(String aResultString)
    {
        Document    doc;
        Text        resultText;
        
        try
        {
            doc = getDocument(new InputSource((new StringReader(aResultString))));
            
            XPathFactory xpathFactory = XPathFactory.newInstance();
            XPath xpath = xpathFactory.newXPath();

            XPathExpression xpathExpr = xpath.compile(
                    "jbi-task/jbi-task-result/frmwk-task-result/" +
                    "frmwk-task-result-details/task-result-details/task-result");

            resultText = (Text) ((NodeList) xpathExpr.evaluate(doc, XPathConstants.NODESET)).item(0).getFirstChild();

            return ("SUCCESS".equalsIgnoreCase(resultText.getData().trim()));
        }
        catch(Throwable t)
        {
            // by default, consider the operation as a failure.
            t.printStackTrace();
            return false;
        }
    }

    /** Synchronized wrapper for non-thread-safe JAXP DocumentBuilder. */
    private synchronized Document getDocument(InputSource source)
        throws Exception
    {
        if (mDocBuilder == null)
        {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setValidating(false);
            mDocBuilder = dbf.newDocumentBuilder();
        }
        
        return mDocBuilder.parse(source);
    }

    /** Install a component. 
     *  @param location path to the component installation archive
     *  @return the name of the component
     */
    private String installComponent(String location)
    {
        ObjectName  installerMBean;
        ObjectName  lifecycleMBean = null;
        String      compId = null;
        String      errorMsg = "";
        boolean     installSuccessful;
        
        // Autoinstall consists of two phases:
        //      Phase 1: installation
        //      Phase 2: installer clean-up and starting the installed component
        // A failure is phase 1 is considered a failed installation.  A failure
        // in phase 2 is considered a success, but any error information is 
        // included in the success log file.
        
        // Phase 1: installation
        try
        {
            // load the component's installer MBean
            installerMBean = (ObjectName)mContext.getMBeanServer().invoke(
                    mInstallationMBean, "loadNewInstaller", 
                    new Object[] {location}, 
                    new String[] {"java.lang.String"});

            // get the component id
            compId = installerMBean.getKeyProperty(
                    mContext.getMBeanNames().COMPONENT_ID_KEY);

            // install the component using its installer MBean
            lifecycleMBean = (ObjectName)mContext.getMBeanServer().invoke(
                    installerMBean, "install", 
                    new Object[] {}, new String[] {});
            
            installSuccessful = true;
        }
        catch (Exception ex)
        { 
            installSuccessful = false;
            errorMsg = ex.getMessage();
        }
        
        // Phase 2: clean-up and start
        try
        {            
            // If the installer was loaded, we need to clean it up
            if (compId != null)
            {
                mContext.getMBeanServer().invoke(
                        mInstallationMBean, "unloadInstaller", 
                        new Object[] {compId, !installSuccessful},
                        new String[] {"java.lang.String", "boolean"});
            }
            
            // Only start the component if the installation was successful
            if (installSuccessful && lifecycleMBean != null)
            {
                mContext.getMBeanServer().invoke(
                    lifecycleMBean, "start",  
                    new Object[] {}, new String[] {});
            }
        }
        catch (Exception ex)
        {
            errorMsg = ex.getMessage();
        }        
        
        removeInstallLogs(location);
        writeLog(location + (installSuccessful ? INSTALL_SUCCESS : INSTALL_FAILURE),
                 errorMsg);        
        return compId;
    }

    /** Uninstall a component. 
     *  @param componentName the name of the component to uninstall
     *  @throws Exception unexpectedly.
     */
    private void uninstallComponent(String componentName)
        throws Exception
    {
        ObjectName  adminMBean;
        ObjectName  lifecycleMBean;
        ObjectName  installerMBean;

        adminMBean = mContext.getMBeanNames().getSystemServiceMBeanName(
                MBeanNames.ServiceName.AdminService,
                MBeanNames.ServiceType.Admin,
                mContext.getEnvironmentContext().getPlatformContext().getInstanceName());

        // load the component's lifecycle MBean
        lifecycleMBean = (ObjectName)mContext.getMBeanServer().invoke(
                adminMBean, "getComponentByName", 
                new Object[] {componentName}, 
                new String[] {"java.lang.String"});

        // invoke shutdown on the component lifecycle
        if (lifecycleMBean == null)
        {
            // the component is not installed
            mLogger.log(Level.FINER, "No need to autouninstall component {0}, as it has already been uninstalled.", componentName);
            return;
        }

        mContext.getMBeanServer().invoke(
            lifecycleMBean, "shutDown",  
            new Object[] {}, new String[] {});

        // create a new installer MBean for the component
        installerMBean = (ObjectName)mContext.getMBeanServer().invoke(
                mInstallationMBean, "loadInstaller", 
                new Object[] {componentName}, 
                new String[] {"java.lang.String"});


        // invoke uninstall on that MBean
        lifecycleMBean = (ObjectName)mContext.getMBeanServer().invoke(
                installerMBean, "uninstall", 
                new Object[] {}, new String[] {});
        
        // now clean up using the unloadInstaller call
        mContext.getMBeanServer().invoke(
                mInstallationMBean, "unloadInstaller", 
                new Object[] {componentName, true}, 
                new String[] {"java.lang.String", "boolean"});
    }

    /** Undeploy a service assembly.
     *  @param saName the name of the service assembly to undeploy
     *  @throws Exception unexpectedly.
     */
    private boolean undeployServiceAssembly(String saName)
        throws Exception
    {
        String results = null;
        String state = "not found";

        boolean deployed = getRegistry().getGenericQuery().
                               isServiceAssemblyDeployed(saName);
        if (!deployed)
        {
            return true;
        }

        try
        {
            state = (String) mContext.getMBeanServer().invoke(
                mDeploymentMBean, "getState",  
                new Object[] {saName}, 
                new String[] {"java.lang.String"});
        }
        catch (Exception e)
        {
            mLogger.log(Level.FINER, "getState({0}) threw {1}.", new Object[]{saName, e});
            return true;
        }

        // if it's already shut down, don't reshut it down
        if (state.equalsIgnoreCase(DeploymentServiceMBean.STARTED) ||
            state.equalsIgnoreCase(DeploymentServiceMBean.STOPPED))
        {
            // shutDown will invoke stop when needed
            mContext.getMBeanServer().invoke(
                mDeploymentMBean, "shutDown",  
                new Object[] {saName}, 
                new String[] {"java.lang.String"});
        }

        results = (String) mContext.getMBeanServer().invoke(
            mDeploymentMBean, "undeploy",  
            new Object[] {saName}, 
            new String[] {"java.lang.String"});

        return parseResultAsSuccess(results);
    }

    /** Install a shared library. 
     *  @param location path to the shared library installation archive
     *  @return the name of the shared library
     */
    private String installSharedLibrary(String location)
    {        
        String slId = null;
        try
        {
            // install the shared library
            slId = (String) mContext.getMBeanServer().invoke(
                                  mInstallationMBean, "installSharedLibrary", 
                                  new Object[] {location}, 
                                  new String[] {"java.lang.String"});
        
            removeInstallLogs(location);
            writeLog(location + INSTALL_SUCCESS, "");
        }
        catch (Exception ex)
        {             
            removeInstallLogs(location);
            writeLog(location + INSTALL_FAILURE, ex.getMessage());
        }
        return slId;
    }

    /** Uninstall a shared library. 
     *  @param slName name of the shared library
     *  @throws Exception unexpectedly.
     */
    private void uninstallSharedLibrary(String slName)
        throws Exception
    {        
        boolean installed = getRegistry().getGenericQuery().
                                isSharedLibraryInstalled(slName);
        if (installed)
        {
            mContext.getMBeanServer().invoke(
                                  mInstallationMBean, "uninstallSharedLibrary", 
                                  new Object[] {slName}, 
                                  new String[] {"java.lang.String"});
        }
    }

    /** Deploy a service assembly. 
     *  @param saName service assembly name
     *  @param location path to the service assembly archive
     */
    private void deployServiceAssembly(String saName, String location)
    {
        boolean     deploySuccessful;
        String      result;
        
        // Autodeploy consists of two phases:
        //      Phase 1: deployment
        //      Phase 2: starting the deploy service assembly
        // A failure is phase 1 is considered a failed deployment.  A failure
        // in phase 2 is considered a success, but any error information is 
        // included in the success log file.
        
        // Phase 1: deployment
        try
        {
            // deploy the service assembly
            result = (String)mContext.getMBeanServer().invoke(
                    mDeploymentMBean, "deploy", 
                    new Object[] {location}, 
                    new String[] {"java.lang.String"});

            deploySuccessful = parseResultAsSuccess(result);
        }
        catch (Exception ex)
        { 
            deploySuccessful = false;
            result = ex.getMessage();
        }

        // Phase 2: start the assembly
        if (deploySuccessful)
        {
            try
            {
                result = (String)mContext.getMBeanServer().invoke(
                        mDeploymentMBean, "start", 
                        new Object[] {saName}, 
                        new String[] {"java.lang.String"});
            }
            catch (Exception ex)
            { 
                result = ex.getMessage();
            }
        }
        
        removeDeployLogs(location);
        writeLog(location + (deploySuccessful ? DEPLOY_SUCCESS : DEPLOY_FAILURE),
                 result);        
    }

    /** Creates a log file with the specified message.  The caller is 
     *  responsible for creating a path with a .success or .failed suffix
     *  consistent with the content of the message.
     */ 
    private void writeLog(String path, String message)
    {
        FileOutputStream fos = null;
        JBIManagementMessage prettyMessage =
            JBIManagementMessage.createJBIManagementMessage(message);

        // use JBIManagementMessage to pretty print the XML (if possible)
        if (prettyMessage != null)
        {
            message = prettyMessage.getMessage();
        }
        
        try
        {
            fos = new FileOutputStream(path);
            fos.write(message.getBytes());
            fos.flush();
        }
        catch (java.io.IOException ioEx)
        {
            ioEx.printStackTrace();
        }
        finally
        {
            if (fos != null)
            {
                try { fos.close(); } 
                catch (Exception ex) {}
            }
        }
    }    

    /** Checks the autoinstall or autodeploy directory for candidate files.  If a
     *  file is found, we check the file suffix (to make sure we are not trying
     *  to install or deploy a status file), and we also check that an existing
     *  timestamp file doesn't already exist, with the same filename.
     *
     *  @param queryType (enum) the type of file we are polling for.
     *  @param topLevelDir the directory to scan for candidate files.
     *  @param statusDir the directory for timestamp files (to exclude matches).
     *  @return a File that is a *not* a status file, nor that already exists
     *  in the status directory.
     */
    synchronized File pollAutoDirectory(PollFunction queryType,
                                        File         topLevelDir,
                                        File         statusDir)
    {
        File candidate = null;

        if (queryType == PollFunction.NEW_FILES)
        {
            if (topLevelDir != null && topLevelDir.isDirectory())
            {        
                mLogger.log(Level.FINEST, "pollAutoDirectory(new) called on {0}", topLevelDir);
                for (File archive : topLevelDir.listFiles())
                {
                    if (archive.isFile())
                    {
                        String fileName = archive.getName();
                        mLogger.log(Level.FINEST, "pollAutoDirectory(new) Found file: {0}", fileName);
                        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
                        mLogger.log(Level.FINEST, "pollAutoDirectory(new): File type of the above is: {0}", fileType);
                        if (fileType.indexOf("_") == -1)
                        {
                            File timeStamp = new File(statusDir, fileName);
                            if (! timeStamp.exists())
                            {
                                mLogger.log(Level.FINER, "pollAutoDirectory(new): Ready to handle {0}", fileName);
                                candidate = archive;
                                break;
                            }
                        }
                    }            
                }
            }
        }
        else if (queryType == PollFunction.DELETED_FILES)
        {
            if (statusDir != null && statusDir.isDirectory())
            {        
                mLogger.log(Level.FINEST, "pollAutoDirectory(deleted) called on {0}", statusDir);
                for (File archive : statusDir.listFiles())
                {
                    if (archive.isFile())
                    {
                        String fileName = archive.getName();
                        mLogger.log(Level.FINEST, "pollAutoDirectory(deleted) Found file: {0}", fileName);
                        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
                        mLogger.log(Level.FINEST, "pollAutoDirectory(deleted): File type of the above is: {0}", fileType);
                        if ((fileType.indexOf("_") == -1) &&
                            (fileType.indexOf(DELIMITER) == -1))
                        {
                            File topFile = new File(topLevelDir, fileName);
                            if (! topFile.exists())
                            {
                                mLogger.log(Level.FINER, "pollAutoDirectory(deleted): Ready to handle {0}", fileName);
                                candidate = archive;
                                break;
                            }
                        }
                    }            
                }
            }
        }
        else if (queryType == PollFunction.UPDATED_FILES)
        {
            if (topLevelDir != null && topLevelDir.isDirectory())
            {        
                mLogger.log(Level.FINEST, "pollAutoDirectory(updated) called on {0}", topLevelDir);
                for (File archive : topLevelDir.listFiles())
                {
                    if (archive.isFile())
                    {
                        String fileName = archive.getName();
                        mLogger.log(Level.FINEST, "pollAutoDirectory(updated) Found file: {0}", fileName);
                        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
                        mLogger.log(Level.FINEST, "pollAutoDirectory(updated): File type of the above is: {0}", fileType);
                        if (fileType.indexOf("_") == -1)
                        {
                            File timeStamp = new File(statusDir, fileName);
                            if (timeStamp.exists() &&
                                (archive.lastModified() > timeStamp.lastModified()))
                            {
                                mLogger.log(Level.FINER, "pollAutoDirectory(updated): Ready to handle {0}", fileName);
                                candidate = archive;
                                break;
                            }
                        }
                    }            
                }
            }
        }

        return candidate;
    }

    /** Check the Configuration MBean for the specified Boolean property.
     * @param aConfigSvcName the name of the config service MBean to query.
     * @param aPermissionName is the name of the attribute to examine.
     * @return "true" or "false" as found in the attribute.
     */
    boolean checkConfigPermission(ObjectName aConfigSvcName, String aPermissionName)
    {
        try
        {
            // Query configuration server for permission bit.
            Object attr = mContext.getMBeanServer().getAttribute(
                                          aConfigSvcName, aPermissionName);

            return ((Boolean) attr);
        }
        catch (Exception e)
        {
            mLogger.log(Level.FINER, "checkConfigPermission({0}, {1}) returned {2}.  Returning default ''false'' value.", new Object[]{aConfigSvcName, aPermissionName, e});
            return false;
        }
    }

    /** Check the Configuration MBean for the specified String property.
     * @param aConfigSvcName the name of the config service MBean to query.
     * @param anAttributeName is the name of the attribute to examine.
     * @return the String value from the Configuration MBean attribute.
     */
    String getConfigAttribute(ObjectName aConfigSvcName, String anAttributeName)
    {
        try
        {
            Object attr = mContext.getMBeanServer().getAttribute(
                                          aConfigSvcName, anAttributeName);

            return (String) attr;
        }
        catch (Exception e)
        {
            mLogger.log(Level.FINER, "checkConfigPermission({0}, {1}) returned {2}.  Returning default ''null'' value.", new Object[]{aConfigSvcName, anAttributeName, e});
            return null;
        }
    }

    /** Initializes autoinstall and autodeploy directories.
     * @param isAutoInstallEnabled true iff the auto install permission bit set.
     * @param isAutoDeployEnabled  true iff the auto deploy permission bit set.
     */
    void initDirectories(boolean isAutoInstallEnabled, boolean isAutoDeployEnabled)
    {   
        // make sure all required directories exist
        if (isAutoInstallEnabled)
        {
            if (null != mAutoInstallDirName)
            {
                if (mAutoInstallDirName.startsWith(File.separator) ||
                     ":".equals(mAutoInstallDirName.substring(1,2))) // C:/blah/blah
                {
                    // treat the directory as an absolute path
                    mAutoInstallDir = new File(mAutoInstallDirName);
                }
                else // test it as a relative path from the jbi install root
                {
                    mAutoInstallDir = new File(mContext.getJbiInstallRoot(),
                                               mAutoInstallDirName);
                }
                mInstallTimestampsDir = new File(mAutoInstallDir, INSTALL_STATUS_DIR);
                if (! mInstallTimestampsDir.exists())
                {
                    mLogger.log(Level.FINE, "initDirectories() creating {0}", mInstallTimestampsDir);
                    mInstallTimestampsDir.mkdirs();
                }
            }
        }

        // make sure all required directories exist
        if (isAutoDeployEnabled)
        {
            if (null != mAutoDeployDirName)
            {
                if (mAutoDeployDirName.startsWith(File.separator) ||
                     ":".equals(mAutoDeployDirName.substring(1,2))) // C:/blah/blah
                {
                    // treat the directory as an absolute path
                    mAutoDeployDir = new File(mAutoDeployDirName);
                }
                else // test it as a relative path from the jbi install root
                {
                    mAutoDeployDir = new File(mContext.getJbiInstallRoot(),
                                              mAutoDeployDirName);
                }
                mDeployTimestampsDir = new File(mAutoDeployDir, DEPLOY_STATUS_DIR);
                if (! mDeployTimestampsDir.exists())
                {
                    mLogger.log(Level.FINE, "initDirectories() creating {0}", mDeployTimestampsDir);
                    mDeployTimestampsDir.mkdirs();
                }
            }
        }
    }

   /**
    * Return the suffix of the string (that comes after the prefix)
    * @param anInputString the string to return the suffix from
    * @param aPrefix the prefix to remove
    * @return the string starting after the prefix
    */
   private String suffix(String anInputString, String aPrefix)
   {
        String[] splitNames = anInputString.split(aPrefix, 2);
        try
        {
            return splitNames[1];
        }
        catch (java.lang.ArrayIndexOutOfBoundsException aioobe)
        {
            mLogger.log(Level.FINER, "suffix({0}, {1}) threw {2}", new Object[]{anInputString, aPrefix, aioobe});
            return null;
        }
   }

   /**
    * Remove all old install logs, in preparation for a new log to be written.
    * @param location the filename to base the log name on.
    */
    private void removeInstallLogs(String location)
    {
        try
        {
            File f1 = new File(location + INSTALL_SUCCESS);
            File f2 = new File(location + INSTALL_FAILURE);
            File f3 = new File(location + UNINSTALL_SUCCESS);
            File f4 = new File(location + UNINSTALL_FAILURE);
            f1.delete();
            f2.delete();
            f3.delete();
            f4.delete();
        }
        catch (Exception e)
        {
            mLogger.log(Level.FINER, "removeInstallLogs({0}) threw {1}", new Object[]{location, e});
        }
    }

   /**
    * Remove all old deploy logs, in preparation for a new log to be written.
    * @param location the filename to base the log name on.
    */
    private void removeDeployLogs(String location)
    {
        try
        {
            File f1 = new File(location + DEPLOY_SUCCESS);
            File f2 = new File(location + DEPLOY_FAILURE);
            File f3 = new File(location + UNDEPLOY_SUCCESS);
            File f4 = new File(location + UNDEPLOY_FAILURE);
            f1.delete();
            f2.delete();
            f3.delete();
            f4.delete();
        }
        catch (Exception e)
        {
            mLogger.log(Level.FINER, "removeDeployLogs({0}) threw {1}", new Object[]{location, e});
        }
    }

    /**
     * Get a handle to the registry
     *
     * @return the persisted registry instance
     */
    private com.sun.jbi.management.registry.Registry getRegistry()
    {
        return (com.sun.jbi.management.registry.Registry) mContext.
                                       getEnvironmentContext().getRegistry();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy