alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
 * Microsystems, Inc. All Rights Reserved.
 */


package org.netbeans.modules.j2ee.deployment.impl;

import org.openide.filesystems.FileUtil;

import javax.enterprise.deploy.shared.ModuleType;
import javax.enterprise.deploy.shared.StateType;
import javax.enterprise.deploy.spi.*;
import javax.enterprise.deploy.spi.status.*;
import javax.enterprise.deploy.spi.exceptions.*;
import org.netbeans.modules.j2ee.deployment.plugins.api.*;
import org.netbeans.modules.j2ee.deployment.devmodules.api.*;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider;
import org.netbeans.modules.j2ee.deployment.impl.ui.DeployProgressUI;
import org.openide.ErrorManager;
import org.netbeans.modules.j2ee.deployment.execution.DeploymentTarget;
import org.netbeans.modules.j2ee.deployment.execution.DeploymentConfigurationProvider;
import org.openide.util.NbBundle;
import org.openide.filesystems.FileObject;

import java.util.Timer;
import java.util.TimerTask;

import java.util.*;
import java.io.*;
import javax.enterprise.deploy.model.DeployableObject;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider;

/**
 * Encapsulates a set of ServerTarget(s), provides a wrapper for deployment
 * help.  This is a throw away object, that get created and used within
 * scope of one deployment execution.
 *
 * Typical user are ServerExecutor and Debugger code, with the following general sequence:
 *
 *      TargetServer ts = new TargetServer(deploymentTarget);
 *      ts.startTargets(deployProgressUI);
 *      TargetModule[] tms = ts.deploy(deployProgressUI);
 *      deploymentTarget.setTargetModules(tms);
 */
public class TargetServer {
    
    private static final long DISTRIBUTE_TIMEOUT = 120000;
    private static final long INCREMENTAL_TIMEOUT = 60000;
    private static final long TIMEOUT = 60000;
    private static final TargetModule[] EMPTY_TARGETMODULE_ARRAY = new TargetModule[0];
    
    private Target[] targets;
    private final ServerInstance instance;
    private final DeploymentTarget dtarget;
    private IncrementalDeployment incremental; //null value signifies don't do incremental
    private boolean debugMode = false;
    private Map availablesMap = null;
    private Set deployedRootTMIDs = new HashSet(); // type TargetModule
    private Set undeployTMIDs = new HashSet(); // TMID
    private Set distributeTargets = new HashSet(); //Target
    private TargetModule[] redeployTargetModules = null;
    private File application = null;
    private File currentContentDir = null;
    private String contextRoot = null;
    private ProgressHandler startEventHandler = null;
    
    public TargetServer(DeploymentTarget target) {
        this.dtarget = target;
        this.instance = dtarget.getServer().getServerInstance();
    }
    
    private void init(DeployProgressUI ui) {
        if (targets == null) {
            instance.start(ui);
            targets = dtarget.getServer().toTargets();
        }        
        incremental = instance.getIncrementalDeployment();
        if (incremental != null && ! checkServiceImplementations())
            incremental = null;

        try {
            FileObject contentFO = dtarget.getModule().getContentDirectory();
            if (contentFO != null) {
                currentContentDir = FileUtil.toFile(contentFO);
            }

            // Note: configuration is not DO so will not be saved automatically on execute
            DeploymentConfigurationProvider dcp = dtarget.getDeploymentConfigurationProvider();
            if (dcp != null)
                dcp.saveOnDemand();
        
        } catch (IOException ioe) {
            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioe);
        }
        
        J2eeModuleProvider.ConfigSupport configSupport = dtarget.getConfigSupport();
        if (J2eeModule.WAR.equals(dtarget.getModule().getModuleType())) {
            contextRoot = configSupport.getWebContextRoot();
        }
        
        processLastTargetModules();
    }
    
    private boolean canFileDeploy(Target[] targetz, DeployableObject deployable) {
        if (targetz == null || targetz.length != 1) {
            ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, NbBundle.getMessage(
            TargetServer.class, "MSG_MoreThanOneIncrementalTargets"));
            return false;
        }
        
        if (!instance.getIncrementalDeployment().canFileDeploy(targetz[0], deployable))
            return false;
        
        return true;
    }
    
    private boolean canFileDeploy(TargetModule[] targetModules, DeployableObject deployable) {
        if (targetModules == null || targetModules.length != 1) {
            ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, NbBundle.getMessage(
            TargetServer.class, "MSG_MoreThanOneIncrementalTargets"));
            return false;
        }
        
        if (!instance.getIncrementalDeployment().canFileDeploy(targetModules[0].getTarget(), deployable))
            return false;
        
        return true;
    }
    
    private AppChangeDescriptor distributeChanges(TargetModule targetModule, DeployProgressUI ui) throws IOException {
        ServerFileDistributor sfd = new ServerFileDistributor(instance, dtarget);
        ui.setProgressObject(sfd);
        ModuleChangeReporter mcr = dtarget.getModuleChangeReporter();
        AppChangeDescriptor acd = sfd.distribute(targetModule, mcr);
        return acd;
    }
    
    private File initialDistribute(Target target, DeployProgressUI ui) {
        InitialServerFileDistributor sfd = new InitialServerFileDistributor(dtarget, target);
        ui.setProgressObject(sfd);
        return sfd.distribute();
    }
    
    private boolean checkServiceImplementations() {
        String missing = null;
        if (instance.getServer().getDeploymentPlanSplitter() == null)
            missing = DeploymentPlanSplitter.class.getName();
        
        if (missing != null) {
            String msg = NbBundle.getMessage(ServerFileDistributor.class, "MSG_MissingServiceImplementations", missing);
            ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL,  msg);
            return false;
        }
        
        return true;
    }
    
    // return list of TargetModule to redeploy
    private TargetModule[] checkUndeployForChangedReferences(Set toRedeploy) {
        // PENDING: what are changed references for ejbmod, j2eeapp???
        if (dtarget.getModule().getModuleType() == J2eeModule.WAR) {
            for (Iterator j=toRedeploy.iterator(); j.hasNext();) {
                TargetModule deployed = (TargetModule) j.next();
                File lastContentDir = (deployed.getContentDirectory() == null) ? null : new File(deployed.getContentDirectory());

                // content dir or context root changes since last deploy
                if ((currentContentDir != null && ! currentContentDir.equals(lastContentDir)) ||
                      (contextRoot != null && ! contextRoot.equals(deployed.getContextRoot()))) {
                    
                    distributeTargets.add(deployed.findTarget());
                    undeployTMIDs.add(deployed.delegate());
                    deployed.remove();
                    j.remove();
                }
            }
        }
        
        return (TargetModule[]) toRedeploy.toArray(new TargetModule[toRedeploy.size()]);
    }
    
    // return list of target modules to redeploy
    private TargetModule[] checkUndeployForSameReferences(Target[] targs) {
        return checkUndeployForSharedReferences(Collections.EMPTY_SET, targs, null);
    }
    private TargetModule[] checkUndeployForSharedReferences(Set toRedeploy, Target[] targs) {
        return checkUndeployForSharedReferences(toRedeploy, targs, null);
    }
    private TargetModule[] checkUndeployForSharedReferences(Set toRedeploy, Target[] targs, Map queryInfo) {
        // PENDING: what are changed references for ejbmod, j2eeapp???
        if (contextRoot == null) {
            return (TargetModule[]) toRedeploy.toArray(new TargetModule[toRedeploy.size()]);
        }
        
        boolean shared = false;
        
        TargetModuleIDResolver tmidResolver = instance.getTargetModuleIDResolver();
        if (tmidResolver != null) {
            if (queryInfo == null) {
                queryInfo = new HashMap();
                queryInfo.put(TargetModuleIDResolver.KEY_CONTEXT_ROOT, contextRoot);
            }
            
            List maybeRedistributeWhenSharedDetected = new ArrayList();
            List maybeRemoveFromRedeployWhenSharedDetected = new ArrayList();
            TargetModuleID[] haveSameReferences = TargetModule.EMPTY_TMID_ARRAY;
            if (targs.length > 1) 
                haveSameReferences = tmidResolver.lookupTargetModuleID(queryInfo, targs);
            for (int i=0; i= deployed.getTimestamp()) {
                    //transfer to distribute
                    if (! dm.isRedeploySupported()) {
                        distributeTargets.add(deployed.findTarget());
                        j.remove();
                    }
                } else {
                    // no need to redeploy
                    j.remove();
                }
            }
        }
        redeployTargetModules = (TargetModule[]) toRedeploy.toArray(new TargetModule[toRedeploy.size()]);
        
        redeployTargetModules = checkUndeployForChangedReferences(toRedeploy);

        Target[] targs = TargetModule.toTarget(redeployTargetModules);
        redeployTargetModules = checkUndeployForSharedReferences(toRedeploy, targs);
    }
    
    private File getApplication() {
        if (application != null) return application;
        try {
            FileObject archiveFO = dtarget.getModule().getArchive();
            if (archiveFO == null) return null;
            application = FileUtil.toFile(archiveFO);
            return application;
        } catch (IOException ioe) {
            ErrorManager.getDefault().log(ErrorManager.EXCEPTION, ioe.getMessage());
            return null;
        }
    }
    
    public boolean startTargets(boolean debugMode, DeployProgressUI ui) {
        this.debugMode = debugMode;
        if (instance.getStartServer().isAlsoTargetServer(null)) {
            if (debugMode) {
                if (! instance.startDebugTarget(null, ui)) {
                    return false;
                }
            } else {
                if (! instance.start(ui)) {
                    return false;
                }
            }
            this.targets = dtarget.getServer().toTargets();
            return true;
        }
        
        instance.start(ui);
        this.targets = dtarget.getServer().toTargets();
        if (debugMode) {
            for (int i=0; i timeout) {
                throw new RuntimeException(NbBundle.getMessage(TargetServer.class, "MSG_DeployTimeout", new Long(timeout/1000)));
            }
        } catch (InterruptedException e) {
            ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
        }
    }
    
    private static String keyOf(TargetModuleID tmid) {
        StringBuffer sb =  new StringBuffer(256);
        sb.append(tmid.getModuleID());
        sb.append("@"); //NOI18N
        sb.append(tmid.getTarget().getName());
        return sb.toString();
    }
    
    //collect root modules into TargetModule with timestamp
    private TargetModuleID[] saveRootTargetModules(TargetModuleID [] modules) {
        long timestamp = System.currentTimeMillis();
        
        Set originals = new HashSet();
        for (int i=0; i 0) {
            Target[] targetz = (Target[]) distributeTargets.toArray(new Target[distributeTargets.size()]);
            
            if (incremental != null && canFileDeploy(targetz, deployable)) {
                DeploymentConfiguration cfg = dtarget.getDeploymentConfigurationProvider().getDeploymentConfiguration();
                File dir = initialDistribute(targetz[0], ui);
                po = incremental.initialDeploy(targetz[0], deployable, cfg, dir);
                handleDeployProgress(ui, po);
            } else {  // standard DM.distribute
                if (getApplication() == null) {
                    throw new RuntimeException(NbBundle.getMessage(TargetServer.class, "MSG_NoArchive"));
                }
                
                ui.addMessage(NbBundle.getMessage(TargetServer.class, "MSG_Distributing", application, Arrays.asList(targetz)));
                po = instance.getDeploymentManager().distribute(targetz, getApplication(), plan);
                handleDeployProgress(ui, po);
            }
        }
        
        // handle increment or redeploy
        if (redeployTargetModules != null && redeployTargetModules.length > 0) {
            if (incremental != null && canFileDeploy(redeployTargetModules, deployable)) {
                AppChangeDescriptor acd = distributeChanges(redeployTargetModules[0], ui);
                if (anyChanged(acd)) {
                    ui.addMessage(NbBundle.getMessage(TargetServer.class, "MSG_IncrementalDeploying", redeployTargetModules[0]));
                    po = incremental.incrementalDeploy(redeployTargetModules[0].delegate(), acd);
                    handleIncrementalProgress(ui, po);
                    
                } else { // return original target modules
                    return dtarget.getTargetModules();
                }
            } else { // standard redeploy
                if (getApplication() == null)
                    throw new IllegalArgumentException(NbBundle.getMessage(TargetServer.class, "MSG_NoArchive"));
                
                ui.addMessage(NbBundle.getMessage(TargetServer.class, "MSG_Redeploying", application));
                TargetModuleID[] tmids = TargetModule.toTargetModuleID(redeployTargetModules);
                po = instance.getDeploymentManager().redeploy(tmids, getApplication(), plan);
                handleDeployProgress(ui, po);
            }
        }
        return (TargetModule[]) deployedRootTMIDs.toArray(new TargetModule[deployedRootTMIDs.size()]);
    }
    
    /**
     * Inform the plugin about the deploy action, even if there was
     * really nothing needed to be deployed.
     *
     * @param modules list of modules which are being deployed
     */
    public void notifyIncrementalDeployment(TargetModuleID[] modules) {
        if (modules !=  null && incremental != null) {
            for (int i = 0; i < modules.length; i++) {
                incremental.notifyDeployment(modules[i]);
            }
        }
    }
    
    public static boolean anyChanged(AppChangeDescriptor acd) {
        return (acd.manifestChanged() || acd.descriptorChanged() || acd.classesChanged()
        || acd.ejbsChanged() || acd.serverDescriptorChanged());
    }
    
    private void handleIncrementalProgress(DeployProgressUI ui, ProgressObject po) {
        handleDeployProgress(ui, po, true);
    }
    private void handleDeployProgress(DeployProgressUI ui, ProgressObject po) {
        handleDeployProgress(ui, po, false);
    }
    
    private void handleDeployProgress(DeployProgressUI ui, ProgressObject po, boolean isIncremental ){
        ProgressListener handler = null;
        try {
            ui.setProgressObject(po);
            
            StateType state = po.getDeploymentStatus().getState();
            if (state == StateType.COMPLETED) {
                ui.addMessage(po.getDeploymentStatus().getMessage());
                handleCompletedDistribute(ui, po, isIncremental);
            } else if (state == StateType.FAILED) {
                ui.addError(NbBundle.getMessage(TargetServer.class, "MSG_DeployFailedWithNoEvent", po.getDeploymentStatus().getMessage()));
            } else {
                if (isIncremental)
                    handler = new TargetServer.IncrementalEventHandler(ui, po);
                else
                    handler = new DistributeEventHandler(ui, po);
                po.addProgressListener(handler);
                sleep(isIncremental ? INCREMENTAL_TIMEOUT : DISTRIBUTE_TIMEOUT);
            }
        } finally {
            if (handler != null)
                po.removeProgressListener(handler);
            if (startEventHandler != null) {
                startEventHandler.unregister();
                startEventHandler = null;
            }
            ui.setProgressObject(null);
        }
    }
    
    private void handleCompletedDistribute(DeployProgressUI ui, final ProgressObject po, boolean isIncremental) {
        TargetModuleID[] modules = po.getResultTargetModuleIDs();
        modules = saveRootTargetModules(modules);
        if (isIncremental) {
            //Note: plugin is responsible for starting module, depending on nature of changes
            wakeUp();
            return;
        }
        
        ProgressObject startPO = instance.getDeploymentManager().start(modules);
        startEventHandler = new ProgressHandler(startPO);
        ui.setProgressObject(startPO);
        
        StateType startState = startPO.getDeploymentStatus().getState();
        if (startState == StateType.COMPLETED || startState == StateType.FAILED) {
            wakeUp();
        }
    }
    
    private void handleAutoUndeploy(DeployProgressUI ui) throws IOException {
        // auto-undeploy if any
        if (undeployTMIDs.size() < 1)
            return;

        TargetModuleID[] tmIDs = (TargetModuleID[]) undeployTMIDs.toArray(new TargetModuleID[undeployTMIDs.size()]);
        ui.addMessage(NbBundle.getMessage(TargetServer.class, "MSG_Undeploying"));
    
        ProgressObject po = instance.getDeploymentManager().stop(tmIDs);
        handleProgressIgnoreFail(ui, po);
        
        po = instance.getDeploymentManager().undeploy(tmIDs);
        handleProgressIgnoreFail(ui, po);
    }

    private void handleProgressIgnoreFail(DeployProgressUI ui, ProgressObject po) {
        ProgressListener handler = null;
        try {
            ui.setProgressObject(po);
            
            StateType state = po.getDeploymentStatus().getState();
            if (state != StateType.COMPLETED && state != StateType.FAILED) {
                handler = new ProgressHandler(po);
                po.addProgressListener(handler);
                sleep(TIMEOUT);
            }
        } finally {
            if (handler != null)
                po.removeProgressListener(handler);
        }
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.