Package com.sun.enterprise.deployment.autodeploy

Source Code of com.sun.enterprise.deployment.autodeploy.AutoDeployer$AutodeployRetryManager$Info

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

/*
* AutoDeployer.java
*
*
* Created on February 19, 2003, 10:21 AM
*/

package com.sun.enterprise.deployment.autodeploy;

import com.sun.enterprise.deployment.deploy.shared.AbstractArchive;
import com.sun.enterprise.deployment.deploy.shared.AbstractArchiveFactory;
import com.sun.enterprise.deployment.deploy.shared.ArchiveFactory;
import com.sun.enterprise.util.io.FileUtils;
import java.io.File;
import java.io.PrintWriter;
import java.io.ByteArrayOutputStream;

import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Properties;
import javax.management.ObjectName;
import javax.management.MBeanServer;
import javax.management.MBeanException;
import com.sun.enterprise.admin.server.core.jmx.InitException;
import com.sun.enterprise.admin.common.ObjectNames;
import com.sun.enterprise.admin.common.constant.DeploymentConstants;
import com.sun.enterprise.config.serverbeans.HttpService;
import com.sun.enterprise.config.serverbeans.HttpListener;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Configs;
import com.sun.enterprise.config.serverbeans.Servers;
import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.ApplicationHelper;
import com.sun.enterprise.config.serverbeans.WebModule;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.config.ConfigException;
import com.sun.enterprise.config.ConfigFactory;
import com.sun.enterprise.config.ConfigBean;
import com.sun.enterprise.instance.InstanceEnvironment;
import com.sun.enterprise.util.i18n.StringManager;
import com.sun.enterprise.instance.ServerManager;
import com.sun.enterprise.server.ServerContext;
import com.sun.enterprise.admin.server.core.AdminService;
import com.sun.enterprise.admin.common.MBeanServerFactory;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.deployment.util.DeploymentProperties;
import com.sun.enterprise.deployment.backend.DeploymentStatus;
import java.util.Properties;
import java.util.HashMap;
import java.util.Date;
import java.io.IOException;
/**
* Handles the logic of deploying the module/app to the required destination.</br>
* The destination can be modified by calling setTarget(), default is first non-admin instance entry from domain.xml</br>
* The specific directory scanner can be set using setDirectoryScanner, default is AutoDeployDirectoryScanner</br>
* Present logic is  using MBean ManagedServerInstance as actual deployment service.
* @author vikas
*/
public class AutoDeployer {
   
    private  ObjectName  mbeanName = null;
    private  MBeanServer mbs=null;
   
    private Boolean verify=null;
    private Boolean forceDeploy=null;
    private Boolean enabled=null;
    private Boolean jspPreCompilation=null;
    private boolean renameOnSuccess = true;
   
    private String targetInstance=null;
    private static final Logger sLogger=AutoDeployControllerImpl.sLogger;
    private static StringManager localStrings =
            StringManager.getManager( AutoDeployer.class );
    private DirectoryScanner directoryScanner=null;
   
    private boolean cancelDeployment =false;
   
    /*
     *Represent the result of attempting autodeployment of a single file.
     *PENDING indicates the file could not be opened as an archive,
     *perhaps because the file was still in the process of being copied when
     *the autodeployer tried to work with it.  PENDING could also mean
     *that the file has changed size since the last time the autodeployer
     *checked it.  It's then reasonable to think it might grow further,
     *so autodeployer waits until the next time through to check it again.
     */
    protected static final int DEPLOY_SUCCESS = 1;
    protected static final int DEPLOY_FAILURE = 2;
    protected static final int DEPLOY_PENDING = 3;
   
    /**
     * archive factory used to create an archive for each file to be deployed -
     *the archive is needed by Depl. Facility
     */
    private final AbstractArchiveFactory archiveFactory = new ArchiveFactory();
   
    private AutodeployRetryManager retryManager = new AutodeployRetryManager();
    /**
     * Creates a new instance of AutoDeployer */
    public AutoDeployer() {
       
        ///initialize other attributes
        verify= new Boolean(false);
        jspPreCompilation=new Boolean(false);
        forceDeploy=new Boolean(true);
        enabled=new Boolean(true);
    }
   
    /**
     * Creates a new instance of AutoDeployer */
    public AutoDeployer(boolean verify, boolean jspPreCompilation) {
       
        ///initialize other attributes
        this.verify= new Boolean(verify);
        this.jspPreCompilation=new Boolean(jspPreCompilation);
        forceDeploy=new Boolean(true);
        enabled=new Boolean(true);
    }
   
    /**
     * set  DirectoryScanner which will be used for filtering out deployeble component
     * @return
     */
    public void setDirectoryScanner(DirectoryScanner ds) {
        directoryScanner=ds;
    }
   
    /**
     * set  target server where the autual deployment will be done
     * @return
     */
    public void setTarget(String target) {
        this.targetInstance = target;
        mbeanName = getMBean(targetInstance);
    }
   
    /**
     * If an archive is successfully autodeployed, file will not be
     * renamed to archive_deployed
     */
    public void disableRenameOnSuccess() {
        renameOnSuccess = false;
    }
   
    /**
     * If an archive is successfully autodeployed will be renamed
     * to archive_deployed
     */
    public void enableRenameOnSuccess() {
        // FIXME - Mahesh
        renameOnSuccess = true;
    }
   
    /**
     *Set whether this AutoDeployer should verify or not.
     *@param boolean verify setting
     */
    public void setVerify(boolean verify) {
        this.verify = new Boolean(verify);
    }
   
    /**
     *Set whether this AutoDeployer should precompile JSPs or not.
     *@param boolean precompilation setting
     */
    public void setJspPreCompilation(boolean jspPreCompilation) {
        this.jspPreCompilation = new Boolean(jspPreCompilation);
    }
   
    /**
     * do deployment for all the deployable components in autoDeployDir dir.
     * @return
     */
    public void deployAll(File autoDeployDir , boolean verify, boolean jspPreCompilation) throws AutoDeploymentException {
        this.verify= new Boolean(verify);
        this.jspPreCompilation=new Boolean(jspPreCompilation);
        deployAll(autoDeployDir);
    }

    /**
     * do deployment for all the deployable components in autoDeployDir dir.
     * @return
     */
    public void deployAll(File autoDeployDir) throws AutoDeploymentException {
        deployAll(autoDeployDir, false);
    }   
   
    /**
     * do deployment for all the deployable components in autoDeployDir dir.
     * @return
     */
    public void deployAll(File autoDeployDir, boolean includeSubDir) throws AutoDeploymentException {
       
       
        //create with default scanner
        if(directoryScanner==null) {
            directoryScanner=new AutoDeployDirectoryScanner();
        }
       
        //set target to default
        if(this.targetInstance == null) {
            setTarget(getDefaultTarget());
        }
       
        File [] files= null;
       
        //get me all deployable entities
        files= directoryScanner.getAllDeployableModules(autoDeployDir, includeSubDir);
       
        /*
         *The following pattern appears in each of the sections below, even though
         *it is described in detail only once here.  This can be improved
         *once autodeploy is converted to use the DeploymentFacility.
         *
         *To support slowly-copied files, the deployApplication (and deployWarmodule, and
         *deployRarModule and deployEjbModule) methods return
         *    DEPLOY_SUCCESS  if the file was successfully autodeployed
         *    DEPLOY_FAILURE  if the file failed to be autodeployed
         *    DEPLOY_PENDING  if the file needs to be tried again later
         *
         *The marker files should be updated only if the result is success or
         *failure.  So for each file of each type, make a separate decision
         *about whether to record the result or not based on the result of
         *the deploy* method.  Note that the boolean is initialized to true
         *so that if an exception is thrown, the file's marker files will be
         *updated.
         */
        if(files != null) {
            for (int i=0; ((i < files.length) && !cancelDeployment);i++) {
                boolean okToRecordResult = true;
                try {
                    okToRecordResult = (deploy(files[i], autoDeployDir,
                    getNameFromFilePath(autoDeployDir, 
                    files[i])) != DEPLOY_PENDING);
                } catch (AutoDeploymentException ae) {
                    //ignore and move to next file
                } finally {
                    if(renameOnSuccess && okToRecordResult)
                        directoryScanner.deployedEntity(autoDeployDir, files[i]);
                }
            }
        }
    }
   
   
   
    /**
     * do undeployment for all deleted applications in autoDeployDir dir.
     * @return
     */
    public void undeployAll(File autoDeployDir) throws AutoDeploymentException {
       
       
        //create with default scanner
        if(directoryScanner==null) {
            directoryScanner=new AutoDeployDirectoryScanner();
        }
       
        if(mbs == null) {
            mbs = getMBeanServer();
        }
        //set target to default
        if(this.targetInstance == null) {
            setTarget(getDefaultTarget());
        }
       
        File[] apps= null;
       
        //get me all apps
        apps= directoryScanner.getAllFilesForUndeployment(autoDeployDir);
       
        //deploying all applications
        if(apps !=null) {
            for (int i=0; i< apps.length && !cancelDeployment;i++) {
                try {
                   
                    boolean stat = this.undeployApplication(apps[i], autoDeployDir,
                    getNameFromFilePath(autoDeployDir, apps[i]));
                    /*
                     * Before managing the marker file for the app, see if
                     * the autodeployer is responsible for deleting this app
                     * file and, if so, delete it.
                     */
                    if (undeployedByRequestFile(apps[i])) {
                        cleanupAppAndRequest(apps[i]);
                    }
                   
                    if (stat)
                        markUndeployed(apps[i]);
                    else
                        markUndeployFailed(apps[i]);
                   
                   
                } catch (AutoDeploymentException ae) {
                    //ignore and move to next file
                    markUndeployFailed(apps[i]);
                } finally {
                    // Mark the application as undeployed both in the case of success & failure.
                    directoryScanner.undeployedEntity(autoDeployDir, apps[i]);
                }
            }
        }
        /////////end for apps
    }
   
    private boolean undeployedByRequestFile(File f) {
        return f instanceof AutoDeployedFilesManager.UndeployRequestedFile;
    }
   
    private void cleanupAppAndRequest(File f) {
        boolean logFine = sLogger.isLoggable(Level.FINE);

        /*
         * Clean up the application file or directory.
         */
        if (f.isDirectory()) {
            if (logFine) {
                sLogger.fine("Deleting autodeployed directory " + f.getAbsolutePath() + " by request");
            }
            FileUtils.liquidate(f);
        } else {
            if (logFine) {
                sLogger.fine("Deleting autodeployed file " + f.getAbsolutePath() + " by request");
            }
            FileUtils.deleteFile(f);
        }
       
        /*
         * Remove the undeploy request file.
         */
        File requestFile = AutoDeployedFilesManager.appToUndeployRequestFile(f);
        if (logFine) {
            sLogger.fine("Deleting autodeploy request file " + requestFile.getAbsolutePath());
        }
        FileUtils.deleteFile(requestFile);
    }
   
    private boolean undeployApplication(File applicationFile, File autodeployDir,
    String name) throws AutoDeploymentException {
        JBIAutoDeployer jad = JBIAutoDeployer.getInstance();
        String saName = jad.getServiceAssemblyName(applicationFile, autodeployDir);
        if (saName == null) {
            return undeployJavaEEArchive(applicationFile, name);
        } else {
            return undeployJbiArchive(saName);
        }
    }

    /**
     * Undeploy a Java EE archive.
     */
    private boolean undeployJavaEEArchive(File applicationFile, String name) throws AutoDeploymentException {
        boolean status = false;
       
        Properties props = getUndeployActionProperties(name);
       
        String[] signature  = new String[]{"java.util.Properties"};
       
        Object[] params     = new Object[]{props};
        sLogger.log(Level.INFO, "Autoundeploying application :" + name);
        status = invokeUndeploymentService(applicationFile.getAbsolutePath(), AutoDeployConstants.UNDEPLOY_METHOD,params,signature);;
        return status;
       
    }

    /**
     * Undeploy a JBI archive.
     */
    private boolean undeployJbiArchive(String saName)
    throws AutoDeploymentException {
        try {
            sLogger.log(Level.INFO, "Autoundeploying application :" + saName);
            JBIAutoDeployer jad = JBIAutoDeployer.getInstance();
            JBIDeployer jd = jad.getDeployer();
            jd.undeploy(getMBeanServer(), saName);
            String msg = localStrings.getString
            ("enterprise.deployment.autodeploy.successfully_autoundeployed",
            saName);
            sLogger.log(Level.INFO, msg);
            return true;
        } catch (Exception e) {
            while (e instanceof MBeanException) {
                e = ((MBeanException)e).getTargetException();
            }
            String msg = localStrings.getString(
            "enterprise.deployment.autodeploy.autoundeploy_failed",saName);
            sLogger.log(Level.INFO, msg);
            msg = localStrings.getString(
            "enterprise.deployment.autodeploy.invocation_exception",saName);
            AutoDeploymentException ae;
            ae=new AutoDeploymentException(msg, e);
            sLogger.log(Level.INFO, ae.getMessage());
            throw ae;
        }
    }
   
    /**
     * set cancel flag, which  will ensure that only if there is any current deployment is in process,</br>
     * it will be completed but the deployer will not do any more deployment.
     * @return
     */
    public void setCancel(boolean value){
        cancelDeployment=value;
    }
   
    /**
     * get cancel flag value
     * @return
     */
    public boolean isCancelled(){
        return cancelDeployment;
    }
   
    /**
     * setup the required internal variables
     */
   
    void init() throws AutoDeploymentException{
        // this sets 'mbs'
        getMBeanServer();
       
        if(targetInstance == null) {
            // side effect -- this also sets mbeanName...
            setTarget(getDefaultTarget());
        }
    }
       
    /**
     *Deploy any type of module.
     *@param file Absolute path of the file to be deployed
     *@param name the module ID of the applications
     *@return status of the deployment attempt: DEPLOY_SUCCESS, DEPLOY_FAILURE, or DEPLOY_PENDING
     *@throws AutoDeploymentException if any invoked method throws an exception
     */
    protected int deploy(File deployablefile, File autodeployDir,
    String name) throws AutoDeploymentException {
       
        int status=DEPLOY_FAILURE;
        if(cancelDeployment) {
            return status;
        }
        String file=deployablefile.getAbsolutePath();
        status = retryManager.testFileAsArchive(file);
        if (status != DEPLOY_SUCCESS) {
            return status;
        }

        JBIAutoDeployer jad = JBIAutoDeployer.getInstance();

        String msg = localStrings.getString(
        "enterprise.deployment.autodeploy.selecting_file",
        deployablefile.getAbsolutePath());
        sLogger.log(Level.INFO, msg);
        if (jad.isJbiArchive(deployablefile)) {
            return deployJbiArchive(deployablefile);
        } else {
            return deployJavaEEArchive(deployablefile, autodeployDir, name);
        }

    }

    /**
     * Deploy a JBI archive.
     */
    int deployJbiArchive(File file) throws AutoDeploymentException {
        int returnStatus=DeploymentStatus.FAILURE;
        try {
            JBIAutoDeployer jad = JBIAutoDeployer.getInstance();
            JBIDeployer jd = jad.getDeployer();
            String saName = jad.getServiceAssemblyName(file);
            jd.deploy(getMBeanServer(), file, saName);
            returnStatus = DeploymentStatus.SUCCESS;
            return DEPLOY_SUCCESS;
        } catch (Exception e) {
            while (e instanceof MBeanException) {
                e = ((MBeanException)e).getTargetException();
            }
            String msg = localStrings.getString
            ("enterprise.deployment.autodeploy.invocation_exception",file);
            AutoDeploymentException ae;
            ae=new AutoDeploymentException(msg, e);
            sLogger.log(Level.INFO, ae.getMessage());
            throw ae;
        } finally {
            markFileAfterDeployment(file, returnStatus);  
        }
    }

    /**
     * Deploy a Java EE archive.
     */
    int deployJavaEEArchive(File deployablefile, File autodeployDir,
    String name) throws AutoDeploymentException {
        int status=DEPLOY_FAILURE;
        // if it's redeploy, first undeploy, then deploy
        String origContextRoot = null;
        if (isModuleDeployed(name)) {
            // preserve the context root information for war redeployment
            try {
                ConfigContext confContext = getConfigContext();
                ConfigBean configBean =  ApplicationHelper.findApplication(
                    confContext, name);
                if (configBean instanceof WebModule) {
                    origContextRoot = ((WebModule)configBean).getContextRoot();
                }
            } catch (ConfigException ce) {
                // ignore
            }
            boolean result =
            undeployApplication(deployablefile, autodeployDir, name);
            if (!result) {
                return DEPLOY_FAILURE;
            }
        }

        Properties props = getDeployActionProperties(deployablefile,name);
        if (origContextRoot != null) {
             props.setProperty(DeploymentProperties.CONTEXT_ROOT,
                 origContextRoot);
        }
        String[] signature  = new String[]{"java.util.Properties"};
       
        Object[] params     = new Object[]{props};
       
        //invoke
        if (invokeDeploymentService(deployablefile, AutoDeployConstants.DEPLOY_METHOD,params,signature)) {
            status = DEPLOY_SUCCESS;
        } else {
            status = DEPLOY_FAILURE;
        }
        return status;
    }

   
    boolean invokeDeploymentService(File deployablefile, String action,
            Object[] params,String[] signature)     throws AutoDeploymentException {
       
        String file=deployablefile.getAbsolutePath();
        boolean status=false;
        int returnStatus = DeploymentStatus.FAILURE;
       
       
        //invoke
        try {
            Object result=getMBeanServer().invoke(getMBeanName(),action, params,signature);
            returnStatus = parseResult(result);
        } catch (Exception e) {
            while (e instanceof MBeanException) {
                e = ((MBeanException)e).getTargetException();
            }
            returnStatus = DeploymentStatus.FAILURE;
            String msg = localStrings.getString
            ("enterprise.deployment.autodeploy.invocation_exception",file);
            AutoDeploymentException ae;
            ae=new AutoDeploymentException(msg, e);
            sLogger.log(Level.INFO, ae.getMessage());
            throw ae;
        } finally {
            status = markFileAfterDeployment(deployablefile, returnStatus);  
        }
        return status;
       
    }

    private boolean markFileAfterDeployment(File file, int returnStatus){
        String msg = null;
        boolean status = false;
        if(returnStatus == DeploymentStatus.SUCCESS) {
            if(renameOnSuccess) {
                markDeployed(file);
            }
            status = true;
            msg = localStrings.getString("enterprise.deployment.autodeploy.successfully_autodeployed",file);
            sLogger.log(Level.INFO, msg);
        } else if (returnStatus == DeploymentStatus.WARNING) {
            if(renameOnSuccess) {
                markDeployed(file);
            }
            status = true;
            msg = localStrings.getString("enterprise.deployment.autodeploy.warning_autodeployed",file);
            sLogger.log(Level.INFO, msg);
        } else if (returnStatus == DeploymentStatus.FAILURE) {
            markDeployFailed(file);
            status = false;
            msg = localStrings.getString("enterprise.deployment.autodeploy.autodeploy_failed",file);
            sLogger.log(Level.INFO, msg);
        }
        return status;
    }
   
    /**
     * get the MBean Name.
     * bnevins 9/16/03
     */
   
    final ObjectName getMBeanName() throws AutoDeploymentException {
        if(mbeanName == null)
            throw new AutoDeploymentException("Internal Error: mbeanName is null");
       
        return mbeanName;
    }
   
    /**
     * get the MBeanServer.  Initialize it if neccessary.
     * Note that the 'final' allows the compiler to inline
     * the method.  So this will be just as fast as accessing the variable
     * directly.
     * bnevins 9/16/03
     */
   
    final MBeanServer getMBeanServer() throws AutoDeploymentException {
        if(mbs == null)
            mbs = MBeanServerFactory.getMBeanServer();
       
        return mbs;
    }
   
   
    private ObjectName getMBean(String instanceName) {
        ObjectName mbean=null;
        try {
            mbean = new ObjectName("com.sun.appserv:type=applications,category=config");
        } catch(Exception e) {
            sLogger.log(Level.SEVERE, "enterprise.deployment.backend.autoDeploymentFailure",
                    new Object[] {e.getMessage()});
        }
        return mbean;
       
    }
   
    private boolean isModuleDeployed (String moduleID) {
        if (moduleID == null) {
            return false;
        }

        try {
            String[] signature = new String[] {"java.lang.String"};
            Object[] params = new Object[] {moduleID};
            Object result = getMBeanServer().invoke(getMBeanName(),
                "getModuleType", params, signature);

            if (result != null) {
                return true;
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }

    private String  getDefaultVirtualServer(String instanceName) {
        String virtualServer=null;
        try {
            ConfigContext context = getConfigContext();
            //Domain domain = (Domain)context.getRootConfigBean();
            //HttpService service = getHttpService(domain,instanceName);
            HttpService service = ServerBeansFactory.getHttpServiceBean(context);
            if(service !=null){
                HttpListener[] hlArray = service.getHttpListener();
                //check not needed since there should always be atleast 1 httplistener
                //if you don't find one, use first one.
                HttpListener ls = null;
                if(hlArray != null && hlArray.length > 0){
                    ls=hlArray[0];
                    //default is the first one that is enabled.
                    for(int i = 0;i<hlArray.length;i++) {
                        if(hlArray[i].isEnabled()) {
                            ls = hlArray[i];
                            break;
                        }
                    }
                }
                if(ls!=null)
                    virtualServer = ls.getDefaultVirtualServer();
            }
        } catch(ConfigException e){
            String msg = localStrings.getString("enterprise.deployment.autodeploy.unable_to_get_virtualserver");
            sLogger.log(Level.WARNING, msg+e.getMessage());
        } catch(Exception e){String msg = localStrings.getString("enterprise.deployment.autodeploy.unable_to_get_virtualserver");
        sLogger.log(Level.WARNING, msg+e.getMessage());
        }
       
        return virtualServer;
       
    }

    private String getDefaultTarget() throws AutoDeploymentException {
        try{
            ConfigContext confContext = getConfigContext();
            Domain domain = (Domain)confContext.getRootConfigBean();
            Servers svrs = domain.getServers();
            Server[] svrArr = svrs.getServer();
            int size = svrArr.length;
            String targetName = null;
            /*I am putting this logic specific for TP, as its decided to deploy directly
             *to instsnce, and not DAS. It need to be changed to next release
             */
            for(int i = 0 ; i< size; i++) {
                if(!svrArr[i].getName().equals("")) {
                    targetName = svrArr[i].getName();
                    break;
                }
            }
            if(targetName == null) {
                sLogger.log(Level.SEVERE, "enterprise.deployment.backend.autoDeploymentFailure",
                        new Object[] {"Target server not found"});
                        throw new AutoDeploymentException("Target Server not found");
            }
           
            return targetName;
        }catch(Exception ex) {
            return null;
        }
    }
   
   
    private ConfigContext getConfigContext() throws ConfigException {
        /*InstanceEnvironment instanceEnvironment =
        new InstanceEnvironment(instanceName);
        String fileUrl  = instanceEnvironment.getConfigFilePath();
        
        ConfigContext configContext   =
        ConfigFactory.createConfigContext(fileUrl);*/
        ServerContext serverContext = AdminService.getAdminService().getContext();
        ConfigContext context = serverContext.getConfigContext();
        return context;
    }
   
   
   
    protected int parseResult(Object result) {
        if(result!=null && result instanceof DeploymentStatus) {
            DeploymentStatus status = (DeploymentStatus) result;
            if (status.getStatus()>DeploymentStatus.WARNING) {
                return DeploymentStatus.SUCCESS;
            } else {
                // ok we got either a warning or an error.
                // parse the deployment status and retrieve failure/warning msg
                ByteArrayOutputStream bos =
                        new ByteArrayOutputStream();
                PrintWriter pw = new PrintWriter(bos);
                DeploymentStatus.parseDeploymentStatus(status, pw);
                byte[] statusBytes = bos.toByteArray();
                String statusString = new String(statusBytes);
               
                if (status.getStatus()==DeploymentStatus.WARNING) {
                    // warning, let's log and continue
                    String msg = localStrings.getString(
                            "enterprise.deployment.warning_occured", statusString);
                    sLogger.log(Level.WARNING, msg);
                    return DeploymentStatus.WARNING;
                } else if (status.getStatus()==DeploymentStatus.FAILURE) {
                    sLogger.log(Level.SEVERE, "enterprise.deployment.backend.autoDeploymentFailure",
                            new Object[] {statusString});
                            return DeploymentStatus.FAILURE;
                }
            }
        }
        return DeploymentStatus.FAILURE;
    }
   
    static String getNameFromFilePath(File autodeployDir, File filePath) {   //creating module name as file name
       
        File parent = filePath.getParentFile();
        String moduleName = null;
        while (!parent.getAbsolutePath().equals(autodeployDir.getAbsolutePath())) {
            if (moduleName==null) {
                moduleName = parent.getName();
            } else {
                moduleName = parent.getName()+"_"+moduleName;
            }
            parent = parent.getParentFile();
        }
        if (moduleName==null) {
            moduleName = filePath.getName();
        } else {
            moduleName = moduleName + "_" + filePath.getName();
        }
        int toIndex = moduleName.lastIndexOf('.');
        if (toIndex > 0) {
            moduleName = moduleName.substring(0, toIndex);
        }
        return moduleName;
    }
   
    // Methods for creating operation status file(s)
    protected void markDeployed(File f) {
        try {
            deleteAllMarks(f);
            getDeployedFile(f).createNewFile();
        } catch (Exception e) {
            //ignore
        }
    }
   
    protected void markDeployFailed(File f) {
        try {
            deleteAllMarks(f);
            getDeployFailedFile(f).createNewFile();
        } catch (Exception e) {
            //ignore
        }
    }
   
    protected void markUndeployed(File f) {
        try {
            deleteAllMarks(f);
            getUndeployedFile(f).createNewFile();
        } catch (Exception e) {
            //ignore
        }
    }
   
    protected void markUndeployFailed(File f) {
        try {
            deleteAllMarks(f);
            getUndeployFailedFile(f).createNewFile();
        } catch (Exception e) {
            //ignore
        }
    }
   
    protected void deleteAllMarks(File f) {
        try {
            getDeployedFile(f).delete();
            getDeployFailedFile(f).delete();
            getUndeployedFile(f).delete();
            getUndeployFailedFile(f).delete();
        } catch (Exception e) {
            //ignore
        }
    }
   
    protected File getDeployedFile(File f) {
        String absPath = f.getAbsolutePath();
        File ret = new File(absPath + AutoDeployConstants.DEPLOYED);
        return ret;
    }
   
    protected File getDeployFailedFile(File f) {
        String absPath = f.getAbsolutePath();
        File ret = new File(absPath + AutoDeployConstants.DEPLOY_FAILED);
        return ret;
    }
   
    protected File getUndeployedFile(File f) {
        String absPath = f.getAbsolutePath();
        File ret = new File(absPath + AutoDeployConstants.UNDEPLOYED);
        return ret;
    }
   
    protected File getUndeployFailedFile(File f) {
        String absPath = f.getAbsolutePath();
        File ret = new File(absPath + AutoDeployConstants.UNDEPLOY_FAILED);
        return ret;
    }
   
    private boolean invokeUndeploymentService(String appFile, String action,
            Object[] params,String[] signature)     throws AutoDeploymentException {
       
        boolean status=false;
        int returnStatus = DeploymentStatus.FAILURE;
        //invoke
        try {
            Object result=getMBeanServer().invoke(getMBeanName(),action, params,signature);
            returnStatus = parseResult(result);
        } catch (Exception e) {
            while (e instanceof MBeanException) {
                e = ((MBeanException)e).getTargetException();
            }
            returnStatus = DeploymentStatus.FAILURE;
            String msg = localStrings.getString("enterprise.deployment.autodeploy.invocation_exception",appFile);
            AutoDeploymentException ae;
            ae=new AutoDeploymentException(msg, e);
            sLogger.log(Level.INFO, ae.getMessage());
            throw ae;
        } finally {
            if(returnStatus == DeploymentStatus.SUCCESS) {
                status = true;
                String msg = localStrings.getString("enterprise.deployment.autodeploy.successfully_autoundeployed",appFile);
                sLogger.log(Level.INFO, msg);
            else if (returnStatus == DeploymentStatus.WARNING) {
                status = true;
                String msg = localStrings.getString("enterprise.deployment.autodeploy.warning_autoundeployed",appFile);
                sLogger.log(Level.INFO, msg);
            } else if (returnStatus == DeploymentStatus.FAILURE) {
                status = false;
                String msg = localStrings.getString("enterprise.deployment.autodeploy.autoundeploy_failed",appFile);
                sLogger.log(Level.INFO, msg);
            }
        }
        return status;
       
    }
   
   
   
    protected Properties getDeployActionProperties(File deployablefile, String ID){
       
        DeploymentProperties dProps = new DeploymentProperties();
        dProps.setArchiveName(deployablefile.getAbsolutePath());
        dProps.setName(ID);
        dProps.setEnable(enabled.booleanValue());
        dProps.setVirtualServers(getDefaultVirtualServer(targetInstance));
        dProps.setForce(forceDeploy.booleanValue());
        dProps.setVerify(verify.booleanValue());
        dProps.setPrecompileJSP(jspPreCompilation.booleanValue());
        dProps.setResourceAction(DeploymentProperties.RES_DEPLOYMENT);
        dProps.setResourceTargetList("server");

        return (Properties)dProps;
    }

    protected Properties getUndeployActionProperties(String name){
        DeploymentProperties dProps = new DeploymentProperties();
        dProps.setName(name);
        dProps.setResourceAction(DeploymentProperties.RES_UNDEPLOYMENT);
        dProps.setResourceTargetList("server");

        return (Properties)dProps;
    }

    /**
     *Manages retrying of autodeployed files in case a file is copied slowly.
     *<p>
     *If a file is copied into the autodeploy directory slowly, it can appear there
     *before the copy has finished, causing the attempt to autodeploy it to fail.
     *This class encapsulates logic to retry such files on successive loops through
     *the autodeployer thread, reporting failure only if the candidate file remains
     *stable in size and cannot be opened after a period of time which defaults below
     *and is configurable using the config property name defined below.
     *<p>
     *The main public entry point is the openAsArchive method, which accepts a file and
     *tries to open it as an archive.  (The archive returned will be useful when
     *AutoDeployer is converted to use the DeploymentFacility.) When AutoDeployer tries
     *and fails to open a file as an archive, it records
     *that fact internally.  The manager adds to or updates
     *a map that describes all such failed files.  If AutoDeployer previously
     *reported failures to open the file and the file's size has been stable
     *for a configurable period of time, then the manager concludes that the
     *file is not simply a slow-copying file but is truly invalid.  In that case
     *it throws an exception.  When a file fails to open as an archive the first time,
     *or if it has failed to open before but its size has changed within the configurable
     *time, then the manager returns a null to indicate that we need to wait before trying
     *to process the file.  Once a file opens successfully, any record of that file is removed
     *from the map.
     */
    class AutodeployRetryManager {
       
        /**
         *Specifies the config property name and default and actual values for the retry limit.
         */
        private final String RETRY_LIMIT_NAME = "com.sun.appserv.autodeploy.retry.limit";
        private final long RETRY_LIMIT_DEFAULT = 30 * 1000; // 30 seconds
        private final long RETRY_LIMIT = Long.getLong(RETRY_LIMIT_NAME, RETRY_LIMIT_DEFAULT).longValue();
       
        /** Maps an invalid File to its corresponding Info object. */
        private HashMap invalidFiles = new HashMap();
       
        /**
         *Records pertinent information about a file judged to be invalid - that is,
         *unrecognizable as a legal archive:
         *<ul>
         *<li>the file object,
         *<li>the length of the file at the most recent check of the file,
         *<li>the time after which no more retries should be attempted.
         *</ul>
         */
        class Info {
            /** File recorded in this Info instance */
            private File file = null;
           
            /** File length the previous time this file was reported as
             * invalid. */
            private long recordedLength = 0;
           
            /** Timestamp after which all retries on this file should stop. */
            private long retryExpiration = 0;
           
            /**
             *Creates a new instance of the Info object for the specified file.
             *@param File to be recorded
             */
            public Info(File file) {
                this.file = file;
                update();
            }
           
            /**
             *Updates the Info object with the file's length and recomputes (if
             *appropriate) the retry due date and the expiration.
             */
            private void update() {
                long currentLength = file.length();
                if (recordedLength != currentLength) {
                    /*
                     *The file's size has changed.  Reset the time for this
                     *file's expiration.
                     */
                    long now = new Date().getTime();
                    retryExpiration = now + RETRY_LIMIT;
                }
                /*
                 *In all cases, update the recorded length with the file's
                 *actual current length.
                 */
                recordedLength = currentLength;
            }
           
            /**
             *Reports whether the file represented by the Info instance is
             *eligible for retry.
             *<p>
             *A file is eligible for retry if its length has changed since
             *the last recorded failure or if the length is stable but has not
             *yet been stable for the expiration period.
             *@return if the file should remain as a candidate for retry
             */
            private boolean isEligibleForRetry() {
                long now = new Date().getTime();
                boolean result = (now < retryExpiration);
                return result;
            }
           
        }
       
        /**
         *Tests to see if the file can be opened as an archive.
         *<p>
         *This method will not be needed if the main autodeployer uses
         *the deployment facility.  This is because the deployment facility
         *method invocations use an archive, so the openFileAsArchive method
         *will be used instead of this one.
         *@param file spec to be tested
         *@return whether the file was opened as an archive (DEPLOY_SUCCESS),
         *   was not but should be tried later (DEPLOY_PENDING), or was
         *   not and should not be tried later (DEPLOY_FAILURE).
         *@throws AutoDeploymentException if an error occurred closing the archive
         */
        int testFileAsArchive(String file) throws AutoDeploymentException {
            int result;
            try {
                File inFile = new File(file);
                if (!inFile.isDirectory()) {
                    // either a j2ee jar file or a .class file
                    if (file.endsWith(".class")) {
                        return DEPLOY_SUCCESS;
                    }
                }
                AbstractArchive arch = openFileAsArchive(file);
                if (arch != null) {
                    result = DEPLOY_SUCCESS;
                    arch.close();
                } else {
                    result = DEPLOY_PENDING;
                }
            } catch (AutoDeploymentException ade) {
                result = DEPLOY_FAILURE;
            } catch (IOException ioe) {
                String msg = localStrings.getString("enterprise.deployment.autodeploy.error_closing_archive", file);
                throw new AutoDeploymentException(msg, ioe);
            }
            return result;
        }
       
        /**
         *Opens the specified file as an archive and tracks files that have
         *failed to open as archives.
         *@param String the file to try opening as an archive
         *@return the AbstractArchive for the file (null if it shoudl be tried later)
         *@throws AutoDeploymenException if the manager has been unable to open
         *the file as an archive past the configured expiration time
         */
        AbstractArchive openFileAsArchive(String file) throws AutoDeploymentException {
            AbstractArchive archive = null;
            File f = new File(file);
            if (shouldOpen(f)) {
                try {
                    /*
                     Try to open the file as an archive and then remove the file, if
                     *it is present, from the map tracking invalid files.
                     */
                    archive = archiveFactory.openArchive(file);
                   
                    recordSuccessfulOpen(f);
                   
                } catch (IOException ioe) {
                    String errorMsg = null;
                    /*
                     *If the archive variable was not assigned a non-null, then the file
                     *is not a valid archive.
                     */
                    if (archive == null) {
                        boolean failedPreviously = recordFailedOpen(f);
                        if ( ! failedPreviously) {
                            Info info = get(f);
                            errorMsg = localStrings.getString("enterprise.deployment.autodeploy.error_opening_start_retry", file, new Date(info.retryExpiration).toString());
                            sLogger.log(Level.INFO, errorMsg);
                        }
                    }
                }
            }
            return archive;
        }
       
        /**
         *Retrieves the Info object describing the specified file.
         *@param File for which the Info object is requested
         *@return Info object for the specified file
         *null if the file is not recorded as invalid
         */
        Info get(File file) {
            Info info = (Info) invalidFiles.get(file);
            return info;
        }
       
        /**
         *Indicates whether the AutoDeployer should try opening the specified
         *file as an archive.
         *<p>
         *The file should be opened if this retry manager has no information
         *about the file or if information is present and the file size is
         *unchanged from the previous failure to open.
         *@return if the file should be opened as an archive
         */
        private boolean shouldOpen(File file) {
            boolean result = true; // default is true in case the file is not being monitored
            String msg = null;
            boolean loggable = sLogger.isLoggable(Level.FINE);
            Info info = (Info) invalidFiles.get(file);
            if (info != null) {
                result = (file.length() == info.recordedLength);
                if (loggable) {
                    if (result) {
                        msg = localStrings.getString("enterprise.deployment.autodeploy.try_stable_length", file.getAbsolutePath());
                    } else {
                        msg = localStrings.getString("enterprise.deployment.autodeploy.no_try_unstable_length", file.getAbsolutePath(), String.valueOf(file.length()));
                    }
                }
                info.update();
            } else {
                if (loggable) {
                    msg = localStrings.getString("enterprise.deployment.autodeploy.try_not_monitored", file.getAbsolutePath());
                }
            }
            if (loggable) {
                sLogger.log(Level.FINE, msg);
            }
            return result;
        }
       
        /**
         *Records the fact that the autodeployer tried but failed to open this file
         *as an archive.
         *@param File the file that could not be interpreted as a legal archive
         *@return true if the file was previously recognized as an invalid one
         *@throws AutoDeploymentException if the file should no longer be retried
         */
        private boolean recordFailedOpen(File file) throws AutoDeploymentException {
            boolean fileAlreadyPresent;
            /*
             *Try to map the file to an existing Info object for it.
             */
            Info info = get(file);
            if (info == null) {
                /*
                 *This file was not previously noted as invalid.  Create a new
                 *entry and add it to the map.
                 */
                fileAlreadyPresent = false;
                info = new Info(file);
                invalidFiles.put(file, info);
                if (sLogger.isLoggable(Level.FINE)) {
                    String msg = localStrings.getString("enterprise.deployment.autodeploy.begin_monitoring", file.getAbsolutePath(), new Date(info.retryExpiration).toString());
                    sLogger.log(Level.FINE, msg);
                }
            } else {
                /*
                 *The file has previously been recorded as invalid.  Update
                 *the recorded info.
                 */
                fileAlreadyPresent = true;
                info.update();
               
                /*
                 *If the file is still eligible for later retries, just return.
                 *If the file size has been stable too long, then conclude that
                 *the file is just an invalid archive and throw an exception
                 *to indicate that.
                 */
                boolean loggable = sLogger.isLoggable(Level.FINE);
                if (info.isEligibleForRetry()) {
                    /*
                     *Just log that the file is still being monitored.
                     */
                    if (loggable) {
                        String msg = localStrings.getString("enterprise.deployment.autodeploy.continue_monitoring", file.getAbsolutePath(), new Date(info.retryExpiration).toString());
                        sLogger.log(Level.FINE, msg);
                    }
                } else {
                    /*
                     *Log that monitoring of this file will end, remove the file from
                     *the map, and throw an exception
                     *with the same message.
                     */
                    String msg = localStrings.getString("enterprise.deployment.autodeploy.abort_monitoring",
                            file.getAbsolutePath(), String.valueOf(RETRY_LIMIT));
                    if (loggable) {
                        sLogger.log(Level.FINE, msg);
                    }
                    invalidFiles.remove(file);
                    throw new AutoDeploymentException(msg);
                }
            }
            return fileAlreadyPresent;
        }
       
        /**
         *Marks a file as successfully opened and no longer subject to retry.
         *@param File that is no longer invalid
         *@return true if the file had been previously recorded as invalid
         */
        private boolean recordSuccessfulOpen(File file) {
            if (sLogger.isLoggable(Level.FINE)) {
                String msg = localStrings.getString("enterprise.deployment.autodeploy.end_monitoring", file.getAbsolutePath());
                sLogger.log(Level.FINE, msg);
            }
            return (invalidFiles.remove(file)) != null;
        }
    }
   
   
   
}
TOP

Related Classes of com.sun.enterprise.deployment.autodeploy.AutoDeployer$AutodeployRetryManager$Info

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