org.glassfish.deployapi.SunDeploymentManager Maven / Gradle / Ivy
Show all versions of payara-micro Show documentation
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. 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_1_1.html
* or packager/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 packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [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.
*/
package org.glassfish.deployapi;
import com.sun.enterprise.util.HostAndPort;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.module.ModulesRegistry;
import com.sun.enterprise.module.single.StaticModulesRegistry;
import com.sun.enterprise.module.bootstrap.StartupContext;
import org.glassfish.api.admin.ProcessEnvironment;
import org.glassfish.deployapi.config.SunDeploymentConfiguration;
import org.glassfish.deployment.client.DeploymentFacility;
import org.glassfish.deployment.client.DeploymentFacilityFactory;
import org.glassfish.deployment.client.ServerConnectionEnvironment;
import org.glassfish.deployment.client.ServerConnectionIdentifier;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.api.deployment.archive.Archive;
import com.sun.enterprise.deploy.shared.ArchiveFactory;
import com.sun.enterprise.deployment.deploy.shared.MemoryMappedArchive;
import org.glassfish.deployment.client.DFDeploymentProperties;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
import com.sun.enterprise.util.LocalStringManagerImpl;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.net.URI;
import javax.enterprise.deploy.spi.DeploymentManager;
import javax.enterprise.deploy.model.DeployableObject;
import javax.enterprise.deploy.shared.CommandType;
import javax.enterprise.deploy.shared.DConfigBeanVersionType;
import javax.enterprise.deploy.shared.ModuleType;
import javax.enterprise.deploy.spi.DeploymentConfiguration;
import javax.enterprise.deploy.spi.exceptions.ConfigurationException;
import javax.enterprise.deploy.spi.exceptions.DConfigBeanVersionUnsupportedException;
import javax.enterprise.deploy.spi.exceptions.InvalidModuleException;
import javax.enterprise.deploy.spi.exceptions.TargetException;
import javax.enterprise.deploy.spi.status.ProgressObject;
import javax.enterprise.deploy.spi.status.ProgressEvent;
import javax.enterprise.deploy.spi.status.DeploymentStatus;
import javax.enterprise.deploy.spi.Target;
import javax.enterprise.deploy.spi.TargetModuleID;
/**
*
* @author Jerome Dochez
* @author Tim Quinn
*/
public class SunDeploymentManager implements DeploymentManager {
// store ID to server connection
private ServerConnectionIdentifier serverId = null;
/** cached reference to a connected DeploymentFacility */
private DeploymentFacility deploymentFacility = null;
private static LocalStringManagerImpl localStrings =
new LocalStringManagerImpl(SunDeploymentManager.class);
private static Locale defaultLocale = Locale.US;
private Locale currentLocale = defaultLocale;
private static Locale[] supportedLocales = { Locale.US };
private String disconnectedMessage = localStrings.getLocalString(
"enterprise.deployapi.spi.disconnectedDM", // NOI18N
"Illegal operation for a disconnected DeploymentManager");// NOI18N
private static final String ENABLED_ATTRIBUTE_NAME = "Enabled"; // NOI18N
private ServiceLocator habitat;
/** Creates a new instance of DeploymentManager */
public SunDeploymentManager() {
}
/** Creates a new instance of DeploymentManager */
public SunDeploymentManager(ServerConnectionIdentifier sci) {
deploymentFacility =
DeploymentFacilityFactory.getDeploymentFacility();
deploymentFacility.connect(sci);
prepareHabitat();
}
/**
* Set additional env vars for the jmx https connector, provided
* by the client. This method is expected to be called right after
* the client retrieves the DeploymentManager, before
* the client makes any calls on the DM that requires MBean Server
* connection.
*/
public void setServerConnectionEnvironment(ServerConnectionEnvironment env) {
serverId.setConnectionEnvironment(env);
}
/**
* Retrieve the list of deployment targets supported by
* this DeploymentManager.
*
* @throws IllegalStateException is thrown when there is a problem getting
* Connection Source
* @return A list of deployment Target designators the
* user may select for application deployment or 'null'
* if there are none.
*/
public Target[] getTargets() throws IllegalStateException {
verifyConnected();
try {
return deploymentFacility.listTargets();
} catch (Throwable e) {
IllegalStateException ex = new IllegalStateException(e.getMessage());
ex.initCause(e);
throw ex;
}
}
/**
* Retrieve the list of J2EE application modules distributed
* to the identified targets and that are currently running
* on the associated server or servers.
*
* @param moduleType A predefined designator for a J2EE
* module type.
*
* @param targetList A list of deployment Target designators
* the user wants checked for module run
* status.
*
* @return An array of TargetModuleID objects representing
* the running modules or 'null' if there
* are none.
*
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @throws TargetException An invalid Target designator
* encountered.
*/
public TargetModuleID[] getRunningModules(ModuleType moduleType,
Target[] targetList) throws TargetException, IllegalStateException {
return getModules(moduleType, targetList, DFDeploymentProperties.RUNNING);
}
/**
* Retrieve the list of J2EE application modules distributed
* to the identified targets and that are currently not
* running on the associated server or servers.
*
* @param moduleType A predefined designator for a J2EE
* module type.
*
* @param targetList A list of deployment Target designators
* the user wants checked for module not
* running status.
*
* @return An array of TargetModuleID objects representing
* the non-running modules or 'null' if
* there are none.
*
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @throws TargetException An invalid Target designator
* encountered.
*/
public TargetModuleID[] getNonRunningModules(ModuleType moduleType,
Target[] targetList) throws TargetException, IllegalStateException {
return getModules(moduleType, targetList, DFDeploymentProperties.NON_RUNNING);
}
/**
* Retrieve the list of all J2EE application modules running
* or not running on the identified targets.
*
* @param moduleType A predefined designator for a J2EE
* module type.
*
* @param targetList A list of deployment Target designators
* the user wants checked for module not
* running status.
*
* @return An array of TargetModuleID objects representing
* all deployed modules running or not or
* 'null' if there are no deployed modules.
*
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @throws TargetException An invalid Target designator
* encountered.
*/
public TargetModuleID[] getAvailableModules(ModuleType moduleType,
Target[] targetList) throws TargetException,
IllegalStateException {
return getModules(moduleType, targetList, DFDeploymentProperties.ALL);
}
/**
*Single method used by several public methods to make sure the deployment manager is
*connected and, if not, throw the IllegalStateException.
*
*@throws IllegalStateException if the deployment manager is not connected.
*/
private void verifyConnected() {
if(isDisconnected()) {
throw new IllegalStateException(disconnectedMessage);
}
}
/**
*Report whether the deployment manager is currently disconnected from the DAS.
*@returns whether the deployment manager is disconnected from the DAS
*/
private boolean isDisconnected(){
if (deploymentFacility == null) {
return true;
}
return (!deploymentFacility.isConnected());
}
/**
*Get all modules in the specified state from the targets specified in the
argument list.
*@param moduleType which returned modules must match
*@param array of Target indicating which targets should be searched for matching modules
*@param state state of the modules
*have for the indicated attribute to be matched
*@exception TargetException if a target was improperly formed
*@exception IllegalStateException if the method is called after release was called
*/
private TargetModuleID[] getModules(ModuleType moduleType, Target[] targetList, String state) throws TargetException, IllegalStateException {
verifyConnected();
if (moduleType==null) {
return null;
}
try {
Vector resultingTMIDs = new Vector();
for (int i = 0; i < targetList.length; i++) {
TargetImpl aTarget = (TargetImpl) targetList[i];
TargetModuleID[] tmids = deploymentFacility._listAppRefs(new Target[] {aTarget}, state, getTypeFromModuleType(moduleType));
addToTargetModuleIDs(tmids, moduleType, aTarget, resultingTMIDs);
}
/*
*Return an array of runtime type TargetModuleIDImpl [].
*/
TargetModuleID [] answer = (TargetModuleID []) resultingTMIDs.toArray(new TargetModuleIDImpl[resultingTMIDs.size()]);
return answer;
} catch(Exception e){
TargetException tg = new TargetException(localStrings.getLocalString(
"enterprise.deployapi.spi.errorgetreqmods",
"Error getting required modules"
));
tg.initCause(e);
throw tg;
}
}
private String getTypeFromModuleType(ModuleType moduleType) {
if (moduleType.equals(ModuleType.WAR)) {
return "web";
} else if (moduleType.equals(ModuleType.EJB)) {
return "ejb";
} else if (moduleType.equals(ModuleType.CAR)) {
return "appclient";
} else if (moduleType.equals(ModuleType.RAR)) {
return "connector";
} else if (moduleType.equals(ModuleType.EAR)) {
return "ear";
}
return null;
}
private ModuleType getModuleTypeFromType(String type) {
if (type.equals("war")) {
return ModuleType.WAR;
} else if (type.equals("ejb")) {
return ModuleType.EJB;
} else if (type.equals("car")) {
return ModuleType.CAR;
} else if (type.equals("rar")) {
return ModuleType.RAR;
} else if (type.equals("ear")) {
return ModuleType.EAR;
}
return null;
}
/**
*Augments a Collection of TargetModuleIDs with new entries for target module IDs of a given module type on the specified target.
*@param tmids array of TargetModuleIDs
*@param type the ModuleType of interest
*@param targetImpl the TargetImpl from which to retrieve modules of the selected type
*@param resultingTMIDs pre-instantiated List to which TargetModuleIDs will be added
*/
private void addToTargetModuleIDs(TargetModuleID[] tmids, ModuleType type, TargetImpl targetImpl, Collection resultingTMIDs) throws IOException {
for (int j = 0;j< tmids.length;j++) {
// Get the host name and port where the application was deployed
HostAndPort webHost = deploymentFacility.getHostAndPort(targetImpl.getName(), tmids[j].getModuleID(), false);
if (tmids[j] instanceof TargetModuleIDImpl) {
((TargetModuleIDImpl)tmids[j]).setModuleType(type);
}
resultingTMIDs.add(tmids[j]);
/*
*Set additional information on the target module ID, depending on what type of
*module this is. For J2EE apps, this includes constructing sub TargetModuleIDs.
*/
try {
if (type.equals(ModuleType.EAR)) {
setJ2EEApplicationTargetModuleIDInfo(tmids[j], webHost);
} else if (type.equals(ModuleType.WAR)) {
setWebApplicationTargetModuleIDInfo(tmids[j], webHost);
}
}
catch(Exception exp){
Logger.getAnonymousLogger().log(Level.WARNING, exp.getLocalizedMessage(), exp);
}
}
}
/**
*Attach child target module IDs to a J2EE application target module ID.
*@param tmid the target module ID for the J2EE application.
*@param targetImpl the target identifying which installation of this module is of interest
*@param webHost the host and port for this target
*/
private void setJ2EEApplicationTargetModuleIDInfo(TargetModuleID tmid,
HostAndPort hostAndPort) throws MalformedURLException, IOException {
TargetImpl targetImpl = (TargetImpl) tmid.getTarget();
try {
List subModuleInfoList = deploymentFacility.getSubModuleInfoForJ2EEApplication(tmid.getModuleID());
for (String subModuleInfo : subModuleInfoList) {
List infoParts = StringUtils.parseStringList(
subModuleInfo, ":");
String subModuleName = infoParts.get(0);
String subModuleID = tmid.getModuleID() + "#" + subModuleName;
String subType = infoParts.get(1);
ModuleType subModuleType = getModuleTypeFromType(subType);
TargetModuleIDImpl childTmid = new TargetModuleIDImpl(
targetImpl, subModuleID);
childTmid.setModuleType(subModuleType);
if (subType.equals("war")) {
// get the web url
URL webURL = new URL("http", hostAndPort.getHost(),
hostAndPort.getPort(), infoParts.get(2));
childTmid.setWebURL(webURL.toExternalForm());
}
if (tmid instanceof TargetModuleIDImpl) {
((TargetModuleIDImpl)tmid).addChildTargetModuleID(
childTmid);
}
}
}
catch(Exception exp){
Logger.getAnonymousLogger().log(Level.WARNING, exp.getLocalizedMessage(), exp);
}
}
/**
*Set additional type-specific information on the target module ID.
*@param tmid the target module ID for the Web app
*@param targetImpl the target identifying which installation of this module is of interest
*@param webHost the host and port for this target
*/
private void setWebApplicationTargetModuleIDInfo(TargetModuleID tmid, HostAndPort webHost) throws MalformedURLException, IOException {
String path = deploymentFacility.getContextRoot(tmid.getModuleID());
if (!path.startsWith("/")) { //NOI18N
path = "/" + path; //NOI18N
}
URL webURL = new URL("http", webHost.getHost(), webHost.getPort(), path); //NOI18N
if (tmid instanceof TargetModuleIDImpl) {
((TargetModuleIDImpl)tmid).setWebURL(webURL.toExternalForm());
}
}
/**
* Retrieve the object that provides server-specific deployment
* configuration information for the J2EE deployable component.
*
* @param dObj An object representing a J2EE deployable component.
* @throws InvalidModuleException The DeployableObject is an
* unknown or unsupport component for this
* configuration tool.
*/
public DeploymentConfiguration createConfiguration(DeployableObject dObj)
throws InvalidModuleException
{
try {
SunDeploymentConfiguration deploymentConfiguration = new SunDeploymentConfiguration(dObj);
deploymentConfiguration.setDeploymentManager(this);
return deploymentConfiguration;
} catch(ConfigurationException e) {
InvalidModuleException ime = new InvalidModuleException(e.getMessage());
ime.initCause(e);
throw ime;
}
}
/**
* The distribute method performs three tasks; it validates the
* deployment configuration data, generates all container specific
* classes and interfaces, and moves the fully baked archive to
* the designated deployment targets.
*
* @param targetList A list of server targets the user is specifying
* this application be deployed to.
* @param moduleArchive The file name of the application archive
* to be disrtibuted.
* @param deploymentPlan The XML file containing the runtime
* configuration information associated with
* this application archive.
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @return ProgressObject an object that tracks and reports the
* status of the distribution process.
*/
public ProgressObject distribute(Target[] targetList,
File moduleArchive, File deploymentPlan)
throws IllegalStateException
{
return deploy(targetList, moduleArchive, deploymentPlan, null /* presetOptions */);
}
/**
* The distribute method performs three tasks; it validates the
* deployment configuration data, generates all container specific
* classes and interfaces, and moves the fully baked archive to
* the designated deployment targets.
*
* @param targetList A list of server targets the user is specifying
* this application be deployed to.
* @param moduleArchive The input stream containing the application
* archive to be disrtibuted.
* @param deploymentPlan The input stream containing the deployment
* configuration information associated with
* this application archive.
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @return ProgressObject an object that tracks and reports the
* status of the distribution process.
*
*/
public ProgressObject distribute(Target[] targetList,
InputStream moduleArchive, InputStream deploymentPlan)
throws IllegalStateException
{
return deploy(targetList, moduleArchive, deploymentPlan, null /* presetOptions */);
}
/**
* The distribute method performs three tasks; it validates the
* deployment configuration data, generates all container specific
* classes and interfaces, and moves the fully baked archive to
* the designated deployment targets.
*
* @param targetList A list of server targets the user is specifying
* this application be deployed to.
* @param moduleType The module type of this application archive.
* @param moduleArchive The input stream containing the application
* archive to be disrtibuted.
* @param deploymentPlan The input stream containing the deployment
* configuration information associated with
* this application archive.
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @return ProgressObject an object that tracks and reports the
* status of the distribution process.
*
*/
public ProgressObject distribute(Target[] targetList, ModuleType type,
InputStream moduleArchive, InputStream deploymentPlan)
throws IllegalStateException
{
DFDeploymentProperties dProps = new DFDeploymentProperties();
dProps.setProperty("type", getTypeFromModuleType(type));
return deploy(targetList, moduleArchive, deploymentPlan, (Properties)dProps);
}
/**
* Start the application running.
*
* Only the TargetModuleIDs which represent a root module
* are valid for being started. A root TargetModuleID has no parent.
* A TargetModuleID with a parent can not be individually started.
* A root TargetModuleID module and all its child modules will be
* started.
*
* @param moduleIDList A array of TargetModuleID objects
* representing the modules to be started.
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @return ProgressObject an object that tracks and reports the
* status of the start operation.
*/
public ProgressObject start(TargetModuleID[] moduleIDList)
throws IllegalStateException
{
return executeCommandUsingFacility(CommandType.START, moduleIDList);
}
/**
* Stop the application running.
*
*
Only the TargetModuleIDs which represent a root module
* are valid for being stopped. A root TargetModuleID has no parent.
* A TargetModuleID with a parent can not be individually stopped.
* A root TargetModuleID module and all its child modules will be
* stopped.
*
* @param moduleIDList A array of TargetModuleID objects
* representing the modules to be stopped.
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @return ProgressObject an object that tracks and reports the
* status of the stop operation.
*/
public ProgressObject stop(TargetModuleID [] moduleIDList)
throws IllegalStateException
{
return executeCommandUsingFacility(CommandType.STOP, moduleIDList);
}
/**
* Remove the application from the target server.
*
*
Only the TargetModuleIDs which represent a root module
* are valid for undeployment. A root TargetModuleID has no parent.
* A TargetModuleID with a parent can not be undeployed. A root
* TargetModuleID module and all its child modules will be undeployed.
* The root TargetModuleID module and all its child modules must
* stopped before they can be undeployed.
*
* @param moduleIDList An array of TargetModuleID objects representing
* the root modules to be stopped.
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @return ProgressObject an object that tracks and reports the
* status of the stop operation.
*/
public ProgressObject undeploy(TargetModuleID[] moduleIDList)
throws IllegalStateException
{
return executeCommandUsingFacility(CommandType.UNDEPLOY, moduleIDList);
}
/**
* This method designates whether this platform vendor provides
* application redeployment functionality. A value of true means
* it is supported. False means it is not.
*
* @return A value of true means redeployment is supported by this
* vendor's DeploymentManager. False means it
* is not.
*/
public boolean isRedeploySupported() {
return true;
}
/**
* (optional)
* The redeploy method provides a means for updating currently
* deployed J2EE applications. This is an optional method for
* vendor implementation.
*
* Redeploy replaces a currently deployed application with an
* updated version. The runtime configuration information for
* the updated application must remain identical to the application
* it is updating.
*
* When an application update is redeployed, all existing client
* connections to the original running application must not be disrupted;
* new clients will connect to the application update.
*
* This operation is valid for TargetModuleIDs that represent a
* root module. A root TargetModuleID has no parent. A root
* TargetModuleID module and all its child modules will be redeployed.
* A child TargetModuleID module cannot be individually redeployed.
* The redeploy operation is complete only when this action for
* all the modules has completed.
*
* @param moduleIDList An array of designators of the applications
* to be updated.
* @param moduleArchive The file name of the application archive
* to be disrtibuted.
* @param deploymentPlan The deployment configuration information
* associated with this application archive.
* @return ProgressObject an object that tracks and reports the
* status of the redeploy operation.
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @throws UnsupportedOperationException this optional command
* is not supported by this implementation.
*/
public ProgressObject redeploy(TargetModuleID[] moduleIDList,
File moduleArchive, File deploymentPlan)
throws UnsupportedOperationException, IllegalStateException
{
try {
/*
*To support multiple different modules in the module ID list, use a TargetModuleIDCollection to
*organize them and work on each module one at a time.
*/
TargetModuleIDCollection coll = new TargetModuleIDCollection(moduleIDList);
for (Iterator it = coll.iterator(); it.hasNext();) {
/*
*The iterator returns one work instance for each module present in the collection.
*/
DeploymentFacilityModuleWork work = (DeploymentFacilityModuleWork) it.next();
/*
*Set the name in the properties according to the moduleID. The module is the same for all the
*targets represented by this single work object.
*/
ProgressObject po = deploy(work.targets(), moduleArchive, deploymentPlan, getRedeployOptions(work.getModuleID()));
/*
*The work instance needs to know about its own progress object, and the
*aggregate progress object needs to also.
*/
work.setProgressObject(po);
coll.getProgressObjectSink().sinkProgressObject(po);
}
return coll.getProgressObjectSink();
} catch (Throwable e) {
return prepareErrorProgressObject(CommandType.REDEPLOY, e);
}
}
/**
* (optional)
* The redeploy method provides a means for updating currently
* deployed J2EE applications. This is an optional method for
* vendor implementation.
*
* Redeploy replaces a currently deployed application with an
* updated version. The runtime configuration information for
* the updated application must remain identical to the application
* it is updating.
*
* When an application update is redeployed, all existing client
* connections to the original running application must not be disrupted;
* new clients will connect to the application update.
*
* This operation is valid for TargetModuleIDs that represent a
* root module. A root TargetModuleID has no parent. A root
* TargetModuleID module and all its child modules will be redeployed.
* A child TargetModuleID module cannot be individually redeployed.
* The redeploy operation is complete only when this action for
* all the modules has completed.
*
* @param moduleIDList An array of designators of the applications
* to be updated.
* @param moduleArchive The input stream containing the application
* archive to be disrtibuted.
* @param deploymentPlan The input stream containing the runtime
* configuration information associated with
* this application archive.
* @return ProgressObject an object that tracks and reports the
* status of the redeploy operation.
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @throws UnsupportedOperationException this optional command
* is not supported by this implementation.
*/
public ProgressObject redeploy(TargetModuleID[] moduleIDList,
InputStream moduleArchive, InputStream deploymentPlan)
throws UnsupportedOperationException, IllegalStateException
{
try {
/*
*To support multiple different modules in the module ID list, use a TargetModuleIDCollection to
*organize them and work on each module one at a time.
*/
TargetModuleIDCollection coll = new TargetModuleIDCollection(moduleIDList);
for (Iterator it = coll.iterator(); it.hasNext();) {
/*
*The iterator returns one work instance for each module present in the collection.
*/
DeploymentFacilityModuleWork work = (DeploymentFacilityModuleWork) it.next();
/*
*Set the name in the properties according to the moduleID. The module is the same for all the
*targets represented by this single work object.
*/
DFDeploymentProperties dProps = getRedeployOptions(work.getModuleID());
// type is not needed for v3 server code now
// dProps.setType(deploymentFacility.getModuleType(work.getModuleID()));
ProgressObject po = deploy(work.targets(), moduleArchive, deploymentPlan, dProps);
/*
*The work instance needs to know about its own progress object, and the
*aggregate progress object needs to also.
*/
work.setProgressObject(po);
coll.getProgressObjectSink().sinkProgressObject(po);
}
return coll.getProgressObjectSink();
} catch (Throwable e) {
return prepareErrorProgressObject(CommandType.REDEPLOY, e);
}
}
/**
* The release method is the mechanism by which the tool signals
* to the DeploymentManager that the tool does not need it to
* continue running connected to the platform.
*
* The tool may be signaling it wants to run in a disconnected
* mode or it is planning to shutdown.
*
* When release is called the DeploymentManager may close any
* J2EE resource connections it had for deployment configuration
* and perform other related resource cleanup. It should not
* accept any new operation requests (i.e., distribute, start
* stop, undeploy, redeploy. It should finish any operations
* that are currently in process. Each ProgressObject associated
* with a running operation should be marked as released (see
* the ProgressObject).
*
*/
public void release() {
/*
*Make sure multiple releases are handled gracefully.
*/
if ( ! isDisconnected() ) {
deploymentFacility = null;
}
}
/**
* Returns the default locale supported by this implementation of
* javax.enterprise.deploy.spi subpackages.
*
* @return Locale the default locale for this implementation.
*/
public Locale getDefaultLocale() {
return defaultLocale;
}
/**
* Returns the active locale this implementation of
* javax.enterprise.deploy.spi subpackages is running.
*
* @return Locale the active locale of this implementation.
*/
public Locale getCurrentLocale() {
return currentLocale;
}
/**
* Set the active locale for this implementation of
* javax.enterprise.deploy.spi subpackages to run.
*
* @throws UnsupportedOperationException the provide locale is
* not supported.
*/
public void setLocale(Locale locale) throws UnsupportedOperationException {
for (int i=0;i
*Several of the deployment facility methods have the same signature except for the name.
*This method collects the pre- and post-processing around those method calls in one place, then
*chooses which of the deployment facility methods to actually invoke based on the
*command type provided as an argument.
*
*@param commandType selects which method should be invoked
*@param moduleIDList array of TargetModuleID to be started
*@exception IllegalArgumentException if the command type is not supported
*@exception IllegalStateException if the deployment manager had been released previously
*/
private ProgressObject executeCommandUsingFacility(
CommandType commandType, TargetModuleID[] targetModuleIDList)
throws IllegalStateException {
verifyConnected();
try {
/*
*Create a temporary collection based on the target module IDs to make it easier to deal
*with the different modules and the set of targets.
*/
TargetModuleIDCollection coll = new TargetModuleIDCollection(targetModuleIDList);
/*
*For each distinct module ID present in the list, ask the deployment facility to
*operate on that module on all the relevant targets.
*/
for (Iterator it = coll.iterator(); it.hasNext();) {
/*
*The iterator returns one work instance for each module present in the collection.
*Each work instance reflects one invocation of a method on the DeploymentFacility.
*/
DeploymentFacilityModuleWork work = (DeploymentFacilityModuleWork) it.next();
ProgressObject po = null;
if (commandType.equals(CommandType.START)) {
po = deploymentFacility.enable(work.targets(), work.getModuleID());
} else if (commandType.equals(CommandType.STOP)) {
po = deploymentFacility.disable(work.targets(), work.getModuleID());
} else if (commandType.equals(CommandType.UNDEPLOY)) {
po = deploymentFacility.undeploy(work.targets(), work.getModuleID());
} else {
throw new IllegalArgumentException(localStrings.getLocalString(
"enterprise.deployapi.spi.unexpcommand",
"Received unexpected deployment facility command ${0}",
new Object [] {commandType.toString()}
));
}
/*
*The new work instance needs to know about its own progress object, and the
*aggregate progress object needs to also.
*/
work.setProgressObject(po);
coll.getProgressObjectSink().sinkProgressObject(po);
}
/*
*Return the single progress object to return to the caller.
*/
return coll.getProgressObjectSink();
} catch (Throwable thr) {
return prepareErrorProgressObject(commandType, thr);
}
}
/**
*Prepare a ProgressObject that reflects an error, with a related Throwable cause.
*@param commandType being processed at the time of the error
*@param throwable that occurred
*@return ProgressObject set to FAILED with linked cause reporting full error info
*/
private ProgressObject prepareErrorProgressObject (CommandType commandType, Throwable thr) {
DeploymentStatus ds = new DeploymentStatusImplWithError(CommandType.DISTRIBUTE, thr);
SimpleProgressObjectImpl progressObj = new SimpleProgressObjectImpl(ds);
ProgressEvent event = new ProgressEvent(progressObj, null /*targetModuleID */, ds);
progressObj.fireProgressEvent(event);
return progressObj;
}
protected Properties getProperties() {
// we don't set name from client side and will let server side
// determine it
DFDeploymentProperties dProps = new DFDeploymentProperties();
dProps.setEnabled(false);
return (Properties)dProps;
}
/**
* The distribute method performs three tasks; it validates the
* deployment configuration data, generates all container specific
* classes and interfaces, and moves the fully baked archive to
* the designated deployment targets.
*
* @param targetList A list of server targets the user is specifying
* this application be deployed to.
* @param moduleArchive The abstraction for the application
* archive to be disrtibuted.
* @param deploymentPlan The archive containing the deployment
* configuration information associated with
* this application archive.
* @param deploymentOptions is a JavaBeans compliant component
* containing all deployment options for this deployable
* unit. This object must be created using the
* BeanInfo instance returned by
* DeploymentConfiguration.getDeploymentOptions
* @throws IllegalStateException is thrown when the method is
* called when running in disconnected mode.
* @return ProgressObject an object that tracks and reports the
* status of the distribution process.
*
*/
public ProgressObject distribute(Target[] targetList,
Archive moduleArchive,
Archive deploymentPlan,
Object deploymentOptions)
throws IllegalStateException {
return null;
}
/**
* Creates a new instance of Archive which can be used to
* store application elements in a layout that can be directly used by
* the application server. Implementation of this method should carefully
* return the appropriate implementation of the interface that suits
* the server needs and provide the fastest deployment time.
* An archive may already exist at the location and elements may be
* read but not changed or added depending on the underlying medium.
* @param path the directory in which to create this archive if local
* storage is a possibility.
* @param name is the desired name for the archive
* @return the writable archive instance
*/
public Archive getArchive(URI path, String name)
throws IOException
{
if (path==null) {
// no particular path was provided, using tmp jar file
File root = File.createTempFile(name,".jar"); //NOI18N
path = root.toURI();
}
ArchiveFactory factory = getArchiveFactory();
boolean exists = false;
if ((path.getScheme().equals("file")) || //NOI18N
(path.getScheme().equals("jar"))) { //NOI18N
File target = new File(path);
exists = target.exists();
} else {
return null;
}
if (exists) {
return factory.openArchive(path);
} else {
return factory.createArchive(path);
}
}
private void prepareHabitat() {
ModulesRegistry registry = new StaticModulesRegistry(getClass().getClassLoader());
ServiceLocator serviceLocator = registry.createServiceLocator("default");
habitat = serviceLocator.getService(ServiceLocator.class);
StartupContext startupContext = new StartupContext();
ServiceLocatorUtilities.addOneConstant(habitat, startupContext);
ServiceLocatorUtilities.addOneConstant(habitat, new ProcessEnvironment(ProcessEnvironment.ProcessType.Other));
}
private ArchiveFactory getArchiveFactory() {
return habitat.getService(ArchiveFactory.class);
}
/**
*Organizes the target module IDs passed by a JSR88 client for easy processing one module ID
*at a time.
*
*Several methods in the JSR88 DeploymentManager interface accept a list of TargetModuleID values,
*and these lists can refer to multiple module IDs and multiple targets.
*Each invocation of a DeploymentFacility method, on the other hand, can work on only a single module
*although with perhaps multiple targets. This class provides a central way of organizing the
*target module IDs as passed from the JSR88 client and making the information for a single
*module ID readily available.
*
*Typically, a client will use three methods:
*
*the constructor - pass a TargetModuleID array as supplied by a client
*the iterator() method, which the client uses to step through the DeploymentFacilityModuleWork
*instances, each representing a single module and perhaps multiple targets.
*the getProgressObjectSink which returns the aggregator for the ProgressObjects
*from each work element
*
*/
protected static class TargetModuleIDCollection {
/* Maps the module ID to that module's instance of DeploymentFacilityModuleWork. */
private HashMap moduleIDToInfoMap = new HashMap();
/* Collects together the individual progress objects into a single aggregate one. */
ProgressObjectSink progressObjectSink = null;
/**
*Create a new instance of TargetModuleIDCollection.
*Accept the array of targetModuleIDs as passed by the JSR88 client and set up the
*internal data structures.
*@param targetModuleIDs array of {@link javax.deployment.api.TargetModuleID TargetModuleID} provided from the calling JSR88 client
*/
public TargetModuleIDCollection(TargetModuleID [] targetModuleIDs) throws IllegalArgumentException {
for (int i = 0; i < targetModuleIDs.length; i++) {
/*
*Make sure that this target module ID has a target that is a TargetImpl and was created by this DM.
*/
Target candidateTarget = targetModuleIDs[i].getTarget();
if ( ! (candidateTarget instanceof TargetImpl)) {
throw new IllegalArgumentException(
localStrings.getLocalString("enterprise.deployapi.spi.nott", //NOI18N
"Expected TargetImpl instance but found instance of {0}", new Object[] {candidateTarget.getClass().getName() } )); //NOI18N
}
String moduleID = targetModuleIDs[i].getModuleID();
/*
*Look for the entry in the hash map for this module.
*/
DeploymentFacilityModuleWork work = (DeploymentFacilityModuleWork) moduleIDToInfoMap.get(moduleID);
if (work == null) {
/*
*This module ID is not yet in the map. Add a work instance for it with the module ID as the key.
*/
work = new DeploymentFacilityModuleWork(moduleID);
moduleIDToInfoMap.put(moduleID, work);
}
/*
*Either the entry already exists or one has been created.
*In either case, add the target to the work to be done with this module.
*/
work.addTarget(candidateTarget);
}
}
/**
*Provides an Iterator over the module work items in the collection.
*The iterator provides one element for each distinct module that appeared in the original
*array of TargetModuleIDs.
*
*@return Iterator over the DeploymentFacilityModuleWork elements in the collection
*/
public Iterator iterator() {
return moduleIDToInfoMap.values().iterator();
}
/**
*Reports the number of elements in the collection.
*This is also a measure of the number of distinct module IDs specified in the TargetModuleID array
*passed to the constructor of the collection.
*@return the number of DeploymentFacilityModuleWork elements contained in the collection
*/
public int size() {
return moduleIDToInfoMap.size();
}
/**
*Returns the aggregate progress object for the collection.
*Creates a new ProgressObjectSink if needed.
*@return ProgressObjectSink
*/
public ProgressObjectSink getProgressObjectSink() {
if (progressObjectSink == null) {
progressObjectSink = new ProgressObjectSink();
}
return progressObjectSink;
}
}
/**
*Encapsulates information used with a single invocation of a DeploymentFacility method--
*that is, one item of "work" the DeploymentFacility is being asked to perform.
*This includes the single target ID of interest (because the DF methods operate on a
*single module), a collection of all the targets to be included in the operation on that
*module, and the progress object resulting from the DF method invocation.
*/
protected static class DeploymentFacilityModuleWork {
/** The module ID this work handles */
private String moduleID = null;
/** The targets this work should affect. */
private Collection targets = new Vector();
/** The ProgressObject for this work returned by the DeploymentFacility method invocation. */
private ProgressObject progressObject = null;
/**
*Creates a new instance of DeploymentFacilityModuleWork.
*@param the module ID common to all work recorded in this instance
*/
public DeploymentFacilityModuleWork(String moduleID) {
this.moduleID = moduleID;
}
/**
*Adds a target to the collection of targets for the work to be done for this distinct module.
*@param the {@link javax.enterprise.deploy.spi.Target Target} to be added for this module
*/
public void addTarget(Target target) {
if ( ! (target instanceof TargetImpl) ) {
throw new IllegalArgumentException(localStrings.getLocalString(
"enterprise.deployapi.spi.unexptargettyp",
"Target must be of type TargetImpl but encountered {0}",
new Object [] {target.getClass().getName()}
));
}
targets.add(target);
}
/**
*Returns an array of {@link javax.enterprise.deploy.spi.Target Target} instances recorded for
*this module. Note the return of an array of runtime type TargetImpl[].
*@return array of Target
*/
public Target [] targets() {
return (Target []) targets.toArray(new TargetImpl[targets.size()]);
}
/**
*Returns the {@link javax.enterprise.deploy.spi.status.ProgressObject ProgressObject} that the
*DeploymentFacility method returned when it was invoked.
*@return the ProgressObject
*/
public ProgressObject getProgressObject() {
return this.progressObject;
}
/**
*Records the {@link javax.enterprise.deploy.spi.status.ProgressObject ProgressObject} that the
*DeploymentFacility returned when its method was invoked.
*@param the ProgressObject provided by the DeploymentFacility
*method
*/
public void setProgressObject (ProgressObject progressObject) {
this.progressObject = progressObject;
}
/**
*Reports the module ID for this instance of DeploymentFacilityModuleWork
*@return the module ID
*/
public String getModuleID() {
return this.moduleID;
}
}
}