Index: org/jboss/deployment/services/DeploymentManagerService.java =================================================================== RCS file: /cvsroot/jboss/jboss-deployment/src/main/org/jboss/deployment/services/DeploymentManagerService.java,v retrieving revision 1.1 diff -u -r1.1 DeploymentManagerService.java --- org/jboss/deployment/services/DeploymentManagerService.java 2 Aug 2005 06:21:22 -0000 1.1 +++ org/jboss/deployment/services/DeploymentManagerService.java 11 Aug 2005 14:27:40 -0000 @@ -13,22 +13,34 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.Set; + import javax.enterprise.deploy.shared.ModuleType; +import javax.enterprise.deploy.spi.TargetModuleID; import javax.enterprise.deploy.spi.exceptions.TargetException; import javax.management.MBeanServerInvocationHandler; +import javax.management.Notification; +import javax.management.NotificationListener; import javax.management.ObjectName; import org.jboss.deployment.DeploymentInfo; import org.jboss.deployment.DeploymentState; import org.jboss.deployment.MainDeployerMBean; +import org.jboss.deployment.scanner.DeploymentScanner; +import org.jboss.deployment.scanner.URLDeploymentScannerMBean; import org.jboss.deployment.spi.SerializableTargetModuleID; +import org.jboss.deployment.spi.TargetModuleIDImpl; import org.jboss.system.ServiceMBeanSupport; import org.jboss.util.file.Files; @@ -36,22 +48,38 @@ * A service that supports the JSR-88 DeploymentManager operations. * * @author Scott.Stark@jboss.org + * @author Fabiano C. de Oliveira * @version $Revision: 1.1 $ */ public class DeploymentManagerService extends ServiceMBeanSupport - implements DeploymentManagerServiceMBean + implements DeploymentManagerServiceMBean, NotificationListener { + private static final String STOPPED_SUFFIX = ".tmp"; + private Map moduleMap = Collections.synchronizedMap(new HashMap()); + private Map pendentDeployments = Collections.synchronizedMap(new HashMap()); /** * The name of the MainDeployer */ private ObjectName mainDeployer; + private ObjectName scanDeployer; private ObjectName carDeployer; private ObjectName earDeployer; private ObjectName ejbDeployer; private ObjectName rarDeployer; private ObjectName warDeployer; + private class PendentDeploymentInfo + { + public SerializableTargetModuleID moduleID = null; + public Throwable deploymentError = null; + + public PendentDeploymentInfo(SerializableTargetModuleID stmid) + { + moduleID = stmid; + } + } + /** * The local directory for uploaded content. */ @@ -65,6 +93,17 @@ { this.mainDeployer = mainDeployer; } + + public ObjectName getDeploymentScanner() + { + return scanDeployer; + } + + public void setDeploymentScanner(ObjectName scanner) + { + this.scanDeployer = scanner; + } + /** * @return The EARDeployer mbean name * @jmx:managed-attribute @@ -181,8 +220,8 @@ // Create the local path File path = new File(deployURL.getFile()); - String archive = path.getName(); - File deployFile = new File(uploadDir, archive); + String archive = path.getName(); + File deployFile = new File(uploadDir, archive + STOPPED_SUFFIX); if( deployFile.exists() == true ) throw new IOException("deployURL("+deployURL+") collides with: "+deployFile.getPath()); @@ -192,7 +231,7 @@ if( parentFile.mkdirs() == false ) throw new IOException("Failed to create local path: "+parentFile); } - + InputStream is = conn.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); byte[] buffer = new byte[4096]; @@ -219,17 +258,34 @@ // Build the local path File path = new File(deployURL.getFile()); String archive = path.getName(); - File deployFile = new File(uploadDir, archive); + File deployFile = new File(uploadDir, archive + STOPPED_SUFFIX); if( deployFile.exists() == false ) - throw new IOException("deployURL("+url+") has no local archive"); + throw new IOException("start("+url+") has no local archive"); MainDeployerMBean proxy = (MainDeployerMBean) MBeanServerInvocationHandler .newProxyInstance(server, mainDeployer, MainDeployerMBean.class, false); - proxy.deploy(deployFile.toURL()); + + File scanFile = new File(uploadDir, archive); + if( scanFile.exists() == true ) + throw new IOException("start("+url+") already started"); + + PendentDeploymentInfo pendent = new PendentDeploymentInfo(moduleID); + pendentDeployments.put(scanFile.toURL(), pendent); + + log.debug("scanning file " + scanFile.toURL() + " and waiting for " + moduleID.getModuleID() + " ..."); + + //deploy using scanner and wait for complete + synchronized(pendent) { + deployFile.renameTo(scanFile); + pendent.wait(); + } + log.debug("completed " + moduleID); + moduleID.setRunning(true); moduleID.clearChildModuleIDs(); + // Repopulate the child modules - DeploymentInfo info = proxy.getDeployment(deployFile.toURL()); + DeploymentInfo info = proxy.getDeployment(scanFile.toURL()); fillChildrenTargetModuleID(moduleID, info); } @@ -237,7 +293,7 @@ { SerializableTargetModuleID moduleID = (SerializableTargetModuleID) moduleMap.get(url); if( moduleID == null ) - throw new IOException("deployURL("+url+") has not been distributed"); + throw new IOException("stop("+url+") has not been distributed"); URL deployURL = new URL(url); // Build the local path @@ -247,9 +303,22 @@ if( deployFile.exists() == false ) throw new IOException("deployURL("+url+") has no local archive"); - MainDeployerMBean proxy = (MainDeployerMBean) MBeanServerInvocationHandler - .newProxyInstance(server, mainDeployer, MainDeployerMBean.class, false); - proxy.undeploy(deployFile.toURL()); + File ignoreFile = new File(uploadDir, archive + STOPPED_SUFFIX); + if( ignoreFile.exists() == true ) + throw new IOException("stop("+url+") already stopped"); + + PendentDeploymentInfo pendent = new PendentDeploymentInfo(moduleID); + pendentDeployments.put(deployFile.toURL(), pendent); + + log.debug("ignoring " + ignoreFile.toURL() + " and waiting for " + moduleID.getModuleID() + " ..."); + + //deploy using scanner and wait for complete + synchronized(pendent) { + deployFile.renameTo(ignoreFile); + pendent.wait(); + } + log.debug("completed " + moduleID); + moduleID.setRunning(false); } @@ -267,9 +336,9 @@ // Build the local path File path = new File(deployURL.getFile()); String archive = path.getName(); - File deployFile = new File(uploadDir, archive); + File deployFile = new File(uploadDir, archive + STOPPED_SUFFIX); if( deployFile.exists() == false ) - throw new IOException("deployURL("+url+") has not been distributed"); + throw new IOException("undeploy("+url+") has not been distributed"); Files.delete(deployFile); moduleMap.remove(url); @@ -278,7 +347,10 @@ public SerializableTargetModuleID[] getAvailableModules(int moduleType) throws TargetException { - ArrayList matches = new ArrayList(); + Set matches = new HashSet(); + + Set hotdeployments = getAvailableHotDeploymentModules(moduleType); + Iterator modules = moduleMap.values().iterator(); while( modules.hasNext() ) { @@ -287,11 +359,92 @@ matches.add(module); } + //list union, so modules deployed using MainDeployer are visible here + //this is necessary because MainDeployer still dont have stop() definition + log.debug("matches list=" + matches + "; hotdeployments=" + hotdeployments); + matches.addAll(hotdeployments); SerializableTargetModuleID[] ids = new SerializableTargetModuleID[matches.size()]; matches.toArray(ids); return ids; } + public void handleNotification(Notification msg, Object handback) + { + log.debug("handleNotification: " + msg); + PendentDeploymentInfo pendent = null; + String type = msg.getType(); + Object userData = msg.getUserData(); + + if (type.equals(DeploymentScanner.URL_DEPLOYMENT_DEPLOYED) || + (type.equals(DeploymentScanner.URL_DEPLOYMENT_UNDEPLOYED))) + { + if (!(userData instanceof URL)) { + return; + } + + URL scanURL = (URL)userData; + pendent = (PendentDeploymentInfo) pendentDeployments.get(scanURL); + synchronized(pendent) { + //complete deployment + pendent.notifyAll(); + } + log.debug("found module=" + pendent.moduleID); + } + else if (type.equals(DeploymentScanner.URL_DEPLOYMENT_FAILED)) + { + if (!(userData instanceof Exception)) { + return; + } + + Exception wrapperException = (Exception)userData; + try + { + URL scanURL = new URL(wrapperException.getMessage()); + pendent = (PendentDeploymentInfo) pendentDeployments.get(scanURL); + pendent.deploymentError = wrapperException.getCause(); + synchronized(pendent) { + //complete deployment + pendent.notifyAll(); + } + log.debug("found module=" + pendent.moduleID); + } + catch (MalformedURLException e) + { + log.error("Error", e); + } + } + } + + public void startService() throws Exception + { + URLDeploymentScannerMBean urlScanner = (URLDeploymentScannerMBean) + MBeanServerInvocationHandler.newProxyInstance(server, scanDeployer, + URLDeploymentScannerMBean.class, false); + URL uploadDirURL = uploadDir.toURL(); + + urlScanner.getFilterInstance(); + + if (!urlScanner.hasURL(uploadDirURL)) { + log.debug("scanner dont have " + uploadDirURL); + urlScanner.addURL(uploadDirURL); + } + + log.debug("dirs=" + urlScanner.getURLList()); + + //listen for deployment events + server.addNotificationListener(scanDeployer, this, null, null); + } + + public void stopService() throws Exception + { + try { + server.removeNotificationListener(scanDeployer, this, null, null); + } + catch(Exception e) { + log.trace("Failed to unregister DeploymentScanner: " + scanDeployer, e); + } + } + private void fillChildrenTargetModuleID(SerializableTargetModuleID moduleID, DeploymentInfo info) { @@ -353,5 +506,77 @@ return type; } - + + /** + * Get all modules deployed by MainDeployer, in other words, modules deployed + * by jsr88 services are NOT returned. + * + * @param moduleType + * @return + */ + private Set getAvailableHotDeploymentModules(int moduleType) + { + String module; + boolean isRunning; + SerializableTargetModuleID tmid = null; + SerializableTargetModuleID[] children = null; + ModuleType type = null; + Set list = new HashSet(); + + try + { + MainDeployerMBean proxy = (MainDeployerMBean) MBeanServerInvocationHandler + .newProxyInstance(server, mainDeployer, MainDeployerMBean.class, false); + Collection col = proxy.listDeployed(); + + for (Iterator it = col.iterator(); it.hasNext();) + { + DeploymentInfo info = (DeploymentInfo)it.next(); + + //get root element and fill the children after + if (info.parent == null) + { + module = info.url.toString(); + isRunning = (DeploymentState.STARTED == info.state); + type = getModuleType(info); + + File path = new File(info.url.getFile()); + if (log.isTraceEnabled()) { + log.trace("path=" + path + "; uploadDir=" + getUploadDir()); + } + + //discart unknows modules and modules deployed from jsr88 dir + if ((type == null) || (path.getParent().equals(getUploadDir().toString()))){ + continue; + } + + tmid = new SerializableTargetModuleID(null, module, + type.getValue(), isRunning); + + //get this root module and set children + fillChildrenTargetModuleID( tmid, info); + + if (tmid.getModuleType() == moduleType) + { + list.add(tmid); + } + + //find child module that match the moduleType + children = tmid.getChildModuleIDs(); + log.debug("tmid=" + tmid + "; children size=" + children.length); + for (int i=0; i < children.length; i++) { + if (((SerializableTargetModuleID)children[i]).getModuleType() == moduleType) { + list.add(children[i]); + } + } + } + } + } + catch (Exception e) + { + log.debug("Failed to get hotdeployment modules", e); + } + + return list; + } } Index: org/jboss/deployment/services/DeploymentManagerServiceMBean.java =================================================================== RCS file: /cvsroot/jboss/jboss-deployment/src/main/org/jboss/deployment/services/DeploymentManagerServiceMBean.java,v retrieving revision 1.1 diff -u -r1.1 DeploymentManagerServiceMBean.java --- org/jboss/deployment/services/DeploymentManagerServiceMBean.java 2 Aug 2005 06:21:22 -0000 1.1 +++ org/jboss/deployment/services/DeploymentManagerServiceMBean.java 11 Aug 2005 14:27:40 -0000 @@ -21,16 +21,20 @@ * DeploymentManager implementation. * * @author Scott.Stark@jboss.org + * @author Fabiano C. de Oliveira * @version $Revision: 1.1 $ */ -public interface DeploymentManagerServiceMBean +public interface DeploymentManagerServiceMBean extends org.jboss.system.ServiceMBean { public File getUploadDir(); public void setUploadDir(File uploadDir); public ObjectName getMainDeployer(); public void setMainDeployer(ObjectName deployer); - + + public ObjectName getDeploymentScanner(); + public void setDeploymentScanner(ObjectName scanner); + ObjectName getEARDeployer(); void setEARDeployer(ObjectName name); Index: org/jboss/deployment/spi/SerializableTargetModuleID.java =================================================================== RCS file: /cvsroot/jboss/jboss-deployment/src/main/org/jboss/deployment/spi/SerializableTargetModuleID.java,v retrieving revision 1.1 diff -u -r1.1 SerializableTargetModuleID.java --- org/jboss/deployment/spi/SerializableTargetModuleID.java 2 Aug 2005 06:18:55 -0000 1.1 +++ org/jboss/deployment/spi/SerializableTargetModuleID.java 11 Aug 2005 14:27:40 -0000 @@ -15,6 +15,7 @@ * A Serializable representation of the TargetModuleID * * @author Scott.Stark@jboss.org + * @author Fabiano C. de Oliveira * @version $Revision: 1.1 $ */ public class SerializableTargetModuleID @@ -75,6 +76,24 @@ return ids; } + public boolean equals(Object obj) + { + boolean result = false; + + if ((obj != null) && (obj instanceof SerializableTargetModuleID)) { + SerializableTargetModuleID target = (SerializableTargetModuleID)obj; + + result = moduleID.equals(target.moduleID) && (moduleType == target.moduleType); + } + + return result; + } + + public int hashCode() + { + return moduleID.hashCode(); + } + public String getModuleID() { return moduleID; Index: org/jboss/deployment/spi/TargetModuleIDImpl.java =================================================================== RCS file: /cvsroot/jboss/jboss-deployment/src/main/org/jboss/deployment/spi/TargetModuleIDImpl.java,v retrieving revision 1.1.1.1.4.1 diff -u -r1.1.1.1.4.1 TargetModuleIDImpl.java --- org/jboss/deployment/spi/TargetModuleIDImpl.java 26 Jun 2005 03:53:03 -0000 1.1.1.1.4.1 +++ org/jboss/deployment/spi/TargetModuleIDImpl.java 11 Aug 2005 14:27:41 -0000 @@ -127,4 +127,25 @@ { childModuleIDs.add(childModuleID); } + + public boolean equals(Object obj) + { + boolean result = false; + + if ((obj != null) && (obj instanceof TargetModuleIDImpl)) { + TargetModuleIDImpl target = (TargetModuleIDImpl)obj; + + result = moduleID.equals(target.moduleID) && + (moduleType.getValue() == target.moduleType.getValue()); + } + + return result; + } + + public int hashCode() + { + return moduleID.hashCode(); + } + + }