Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » deployment » [javadoc | source]
    1   /*
    2    * JBoss, Home of Professional Open Source
    3    * Copyright 2005, JBoss Inc., and individual contributors as indicated
    4    * by the @authors tag. See the copyright.txt in the distribution for a
    5    * full listing of individual contributors.
    6    *
    7    * This is free software; you can redistribute it and/or modify it
    8    * under the terms of the GNU Lesser General Public License as
    9    * published by the Free Software Foundation; either version 2.1 of
   10    * the License, or (at your option) any later version.
   11    *
   12    * This software is distributed in the hope that it will be useful,
   13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   15    * Lesser General Public License for more details.
   16    *
   17    * You should have received a copy of the GNU Lesser General Public
   18    * License along with this software; if not, write to the Free
   19    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   20    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   21    */
   22   package org.jboss.deployment;
   23   
   24   import java.io.BufferedInputStream;
   25   import java.io.BufferedOutputStream;
   26   import java.io.File;
   27   import java.io.FileOutputStream;
   28   import java.io.IOException;
   29   import java.io.InputStream;
   30   import java.io.OutputStream;
   31   import java.net.MalformedURLException;
   32   import java.net.URL;
   33   import java.net.URLClassLoader;
   34   import java.util.ArrayList;
   35   import java.util.Collection;
   36   import java.util.Collections;
   37   import java.util.Comparator;
   38   import java.util.HashMap;
   39   import java.util.Iterator;
   40   import java.util.LinkedList;
   41   import java.util.List;
   42   import java.util.ListIterator;
   43   import java.util.Map;
   44   import java.util.Set;
   45   import java.util.StringTokenizer;
   46   import java.util.jar.Attributes;
   47   import java.util.jar.Manifest;
   48   import javax.management.MBeanServer;
   49   import javax.management.MalformedObjectNameException;
   50   import javax.management.Notification;
   51   import javax.management.ObjectName;
   52   
   53   import org.jboss.deployers.client.spi.DeployerClient;
   54   import org.jboss.deployers.client.spi.Deployment;
   55   import org.jboss.deployers.structure.spi.DeploymentContext;
   56   import org.jboss.deployers.structure.spi.DeploymentUnit;
   57   import org.jboss.deployers.structure.spi.main.MainDeployerStructure;
   58   import org.jboss.deployers.vfs.spi.client.VFSDeployment;
   59   import org.jboss.deployers.vfs.spi.client.VFSDeploymentFactory;
   60   import org.jboss.kernel.spi.dependency.KernelController;
   61   import org.jboss.system.ServiceMBeanSupport;
   62   import org.jboss.system.server.ServerConfig;
   63   import org.jboss.system.server.ServerConfigLocator;
   64   import org.jboss.util.file.Files;
   65   import org.jboss.util.file.JarUtils;
   66   import org.jboss.util.stream.Streams;
   67   import org.jboss.virtual.VFS;
   68   import org.jboss.virtual.VirtualFile;
   69   
   70   /**
   71    * The legacy component for deployer management. This now simply delegates to the
   72    * Main
   73    *
   74    * @deprecated see org.jboss.deployers.spi.deployment.MainDeployer
   75    * 
   76    * @author <a href="mailto:marc.fleury@jboss.org">Marc Fleury</a>
   77    * @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a>
   78    * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
   79    * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
   80    * @author adrian@jboss.org
   81    * @version $Revision: 69696 $
   82    */
   83   public class MainDeployer extends ServiceMBeanSupport
   84      implements Deployer, MainDeployerMBean
   85   {
   86      /** The controller */
   87      private KernelController controller;
   88      private DeployerClient delegate;
   89      private Map<URL, String> contextMap = Collections.synchronizedMap(new HashMap<URL, String>());
   90   
   91      /** The deployment factory */
   92      private VFSDeploymentFactory deploymentFactory = VFSDeploymentFactory.getInstance();
   93      
   94      /**
   95       * The variable <code>serviceController</code> is used by the
   96       * checkIncompleteDeployments method to ask for lists of mbeans
   97       * with deployment problems.
   98       */
   99      private ObjectName serviceController;
  100   
  101      /** Deployers **/
  102      private final LinkedList deployers = new LinkedList();
  103   
  104      /** A Map of URL -> DeploymentInfo */
  105      private final Map deploymentMap = Collections.synchronizedMap(new HashMap());
  106   
  107      /** A list of all deployments that have deployers. */
  108      private final List deploymentList = new ArrayList();
  109   
  110      /** A list of all deployments that do not have deployers. */
  111      private final List waitingDeployments = new ArrayList();
  112   
  113      /** A helper for sorting deployment URLs. */
  114      private final DeploymentSorter sorter = new DeploymentSorter();
  115   
  116      /** A helper for sorting deploymentInfos */
  117      private final Comparator infoSorter = new DeploymentInfoComparator(sorter);
  118   
  119      /** Helper class handling the SuffixOrder and EnhancedSuffixOrder attributes */
  120      private final SuffixOrderHelper suffixOrderHelper = new SuffixOrderHelper(sorter);
  121      
  122      /** Should local copies be made of resources on the local file system */
  123      private boolean copyFiles = true;
  124   
  125      /** The temporary directory for deployments. */
  126      private File tempDir;
  127   
  128      /** The string naming the tempDir **/
  129      private String tempDirString;
  130   
  131      /**
  132       * Explict no-args contsructor for JMX.
  133       */
  134      public MainDeployer()
  135      {
  136         // Is there a better place to obtain startup information?
  137         String localCopy = System.getProperty("jboss.deploy.localcopy");
  138         if (localCopy != null && (
  139             localCopy.equalsIgnoreCase("false") ||
  140             localCopy.equalsIgnoreCase("no") ||
  141             localCopy.equalsIgnoreCase("off")))
  142         {
  143            log.debug("Disabling local copies of file: urls");
  144            copyFiles = false;
  145         }
  146      }
  147   
  148      public DeployerClient getKernelMainDeployer()
  149      {
  150         return delegate;
  151      }
  152      public void setKernelMainDeployer(DeployerClient delegate)
  153      {
  154         this.delegate = delegate;
  155      }
  156   
  157      public KernelController getController()
  158      {
  159         return controller;
  160      }
  161   
  162      public void setController(KernelController controller)
  163      {
  164         this.controller = controller;
  165      }
  166   
  167      /** Get the flag indicating whether directory content will be deployed
  168       *
  169       * @return the file copy flag
  170       * @jmx.managed-attribute
  171       */
  172      public boolean getCopyFiles()
  173      {
  174         return copyFiles;
  175      }
  176      /** Set the flag indicating whether directory content will be deployed. The
  177       * default value is taken from the jboss.deploy.localcopy system
  178       * property.
  179       *
  180       * @param copyFiles the local copy flag value
  181       * @jmx.managed-attribute
  182       */
  183      public void setCopyFiles(boolean copyFiles)
  184      {
  185         this.copyFiles = copyFiles;
  186      }
  187   
  188      /** Get the temp directory
  189       *
  190       * @return the path to the local tmp directory
  191       * @jmx.managed-attribute
  192       */
  193      public File getTempDir()
  194      {
  195         return tempDir;
  196      }
  197      /** Set the temp directory
  198       *
  199       * @param tempDir the path to the local tmp directory
  200       * @jmx.managed-attribute
  201       */
  202      public void setTempDir(File tempDir)
  203      {
  204         this.tempDir = tempDir;
  205      }
  206   
  207      /** Get the temp directory
  208       *
  209       * @return the path to the local tmp directory
  210       * @jmx.managed-attribute
  211       */
  212      public String getTempDirString()
  213      {
  214         return tempDirString;
  215      }
  216   
  217      /** Get the ordering of the deployment suffixes
  218       *
  219       * @return the ordering of the deployment suffixes
  220       * @jmx.managed-attribute
  221       */
  222      public String[] getSuffixOrder()
  223      {
  224         return suffixOrderHelper.getSuffixOrder();
  225      }
  226      
  227      /** Get the enhanced suffix order
  228       * 
  229       * @return the enhanced suffix order 
  230       * @jmx.managed-attribute
  231       */
  232      public String[] getEnhancedSuffixOrder()
  233      {
  234         return suffixOrderHelper.getEnhancedSuffixes();
  235      }
  236      
  237      /** Set the enhanced suffix order
  238       *
  239       * @param enhancedSuffixOrder the enhanced suffix order
  240       * @jmx.managed-attribute
  241       */
  242      public void setEnhancedSuffixOrder(String[] enhancedSuffixOrder)
  243      {
  244         suffixOrderHelper.setEnhancedSuffixes(enhancedSuffixOrder);
  245      }
  246     
  247      /**
  248       * Describe <code>setServiceController</code> method here.
  249       *
  250       * @param serviceController an <code>ObjectName</code> value
  251       * @jmx.managed-attribute
  252       */
  253      public void setServiceController(final ObjectName serviceController)
  254      {
  255         this.serviceController = serviceController;
  256      }
  257   
  258      /**
  259       * The <code>listDeployed</code> method returns a collection of DeploymemtInfo
  260       * objects for the currently deployed packages.
  261       *
  262       * @return a <code>Collection</code> value
  263       * @jmx.managed-operation
  264       */
  265      public Collection listDeployed()
  266      {
  267         synchronized (deploymentList)
  268         {
  269            log.debug("deployment list string: " + deploymentList);
  270            return new ArrayList(deploymentList);
  271         }
  272      }
  273   
  274      /**
  275       * The <code>listDeployedModules</code> method returns a collection of
  276       * SerializableDeploymentInfo objects for the currently deployed packages.
  277       *
  278       * @return a <code>Collection</code> value
  279       * @jmx.managed-operation
  280       */
  281      public Collection listDeployedModules()
  282      {
  283         log.debug("listDeployedModules");
  284   
  285         HashMap map = new HashMap();
  286         synchronized (deploymentList)
  287         {
  288            Collection col = new ArrayList(deploymentList);
  289   
  290            // create a map entry for each deployment
  291            for (Iterator it = col.iterator(); it.hasNext();)
  292            {
  293               DeploymentInfo info = (DeploymentInfo) it.next();
  294               map.put(info.url, new SerializableDeploymentInfo(info));
  295               // assign parent and sub deployments
  296               fillParentAndChildrenSDI(info, map);
  297            }
  298         }
  299   
  300         // map.values is not serializable, so we copy
  301         return new ArrayList(map.values());
  302      }
  303   
  304      /**
  305       * Describe <code>listDeployedAsString</code> method here.
  306       *
  307       * @return a <code>String</code> value
  308       * @jmx.managed-operation
  309       */
  310      public String listDeployedAsString()
  311      {
  312         return "<pre>" + listDeployed() + "</pre>";
  313      }
  314   
  315      /**
  316       * The <code>listIncompletelyDeployed</code> method returns a list of packages that have
  317       * not deployed completely. The toString method will include any exception in the status
  318       * field.
  319       *
  320       * @return a <code>Collection</code> value
  321       * @jmx.managed-operation
  322       */
  323      public Collection listIncompletelyDeployed()
  324      {
  325         List id = new ArrayList();
  326         List copy;
  327         synchronized (deploymentList)
  328         {
  329            copy = new ArrayList(deploymentList);
  330         }
  331         for (Iterator i = copy.iterator(); i.hasNext();)
  332         {
  333            DeploymentInfo di = (DeploymentInfo)i.next();
  334            if (!"Deployed".equals(di.status) && !"Starting".equals(di.status))
  335            {
  336               id.add(di);
  337            } // end of if ()
  338   
  339         } // end of for ()
  340         return id;
  341      }
  342   
  343      /**
  344       * The <code>listWaitingForDeployer</code> method returns a collection
  345       * of the packages that currently have no identified deployer.
  346       *
  347       * @return a <code>Collection</code> value
  348       * @jmx.managed-operation
  349       */
  350      public Collection listWaitingForDeployer()
  351      {
  352         synchronized (waitingDeployments)
  353         {
  354            return new ArrayList(waitingDeployments);
  355         }
  356      }
  357   
  358      /**
  359       * The <code>addDeployer</code> method registers a deployer with the main deployer.
  360       * Any waiting packages are tested to see if the new deployer will deploy them.
  361       *
  362       * @param deployer a <code>SubDeployer</code> value
  363       * @jmx.managed-operation
  364       */
  365      public void addDeployer(final SubDeployer deployer)
  366      {
  367         log.debug("Adding deployer: " + deployer);
  368         ObjectName deployerName = deployer.getServiceName();
  369         
  370         synchronized(deployers)
  371         {
  372            deployers.addFirst(deployer);
  373            try
  374            {
  375               String[] suffixes = (String[]) server.getAttribute(deployerName, "EnhancedSuffixes");
  376               suffixOrderHelper.addEnhancedSuffixes(suffixes);
  377            }
  378            catch(Exception e)
  379            {
  380               log.debug(deployerName + " does not support EnhancedSuffixes");
  381               suffixOrderHelper.addSuffixes(deployer.getSuffixes(), deployer.getRelativeOrder());
  382            }
  383         }
  384         
  385         // Send a notification about the deployer addition
  386         Notification msg = new Notification(ADD_DEPLOYER, this, getNextNotificationSequenceNumber());
  387         msg.setUserData(deployerName);
  388         sendNotification(msg);
  389   
  390         synchronized (waitingDeployments)
  391         {
  392            List copy = new ArrayList(waitingDeployments);
  393            waitingDeployments.clear();
  394            for (Iterator i = copy.iterator(); i.hasNext();)
  395            {
  396               DeploymentInfo di = (DeploymentInfo)i.next();
  397               log.debug("trying to deploy with new deployer: " + di.shortName);
  398               try
  399               {
  400                  di.setServer(server);
  401                  deploy(di);
  402               }
  403               catch (DeploymentException e)
  404               {
  405                  log.error("DeploymentException while trying to deploy a package with a new deployer", e);
  406               } // end of try-catch
  407            } // end of for ()
  408         }
  409      }
  410      
  411      /**
  412       * The <code>removeDeployer</code> method unregisters a deployer with the MainDeployer.
  413       * Deployed packages deployed with this deployer are undeployed.
  414       *
  415       * @param deployer a <code>SubDeployer</code> value
  416       * @jmx.managed-operation
  417       */
  418      public void removeDeployer(final SubDeployer deployer)
  419      {
  420         log.debug("Removing deployer: " + deployer);
  421         ObjectName deployerName = deployer.getServiceName();
  422         boolean removed = false;
  423         
  424         synchronized(deployers)
  425         {
  426            removed = deployers.remove(deployer);
  427            try
  428            {
  429               String[] suffixes = (String[]) server.getAttribute(deployerName, "EnhancedSuffixes");
  430               suffixOrderHelper.removeEnhancedSuffixes(suffixes);
  431            }
  432            catch(Exception e)
  433            {
  434               log.debug(deployerName + " does not support EnhancedSuffixes");
  435               suffixOrderHelper.removeSuffixes(deployer.getSuffixes(), deployer.getRelativeOrder());
  436            }
  437         }
  438         
  439         // Send a notification about the deployer removal
  440         if (removed)
  441         {
  442            Notification msg = new Notification(REMOVE_DEPLOYER, this, getNextNotificationSequenceNumber());
  443            msg.setUserData(deployerName);
  444            sendNotification(msg);
  445         }
  446   
  447         List copy;
  448         synchronized (deploymentList)
  449         {
  450            copy = new ArrayList(deploymentList);
  451         }
  452         for (Iterator i = copy.iterator(); i.hasNext(); )
  453         {
  454            DeploymentInfo di = (DeploymentInfo)i.next();
  455            if (di.deployer == deployer)
  456            {
  457               undeploy(di);
  458               di.deployer = null;
  459               synchronized (waitingDeployments)
  460               {
  461                  waitingDeployments.add(di);
  462               }
  463            }
  464         }
  465      }
  466   
  467      /**
  468       * The <code>listDeployers</code> method returns a collection of ObjectNames of
  469       * deployers registered with the MainDeployer.
  470       *
  471       * @return a <code>Collection<ObjectName></code> value
  472       * @jmx.managed-operation
  473       */
  474      public Collection listDeployers()
  475      {
  476         ArrayList deployerNames = new ArrayList();
  477         synchronized(deployers)
  478         {
  479            for(int n = 0; n < deployers.size(); n ++)
  480            {
  481               SubDeployer deployer = (SubDeployer) deployers.get(n);
  482               ObjectName name = deployer.getServiceName();
  483               deployerNames.add(name);
  484            }
  485         }
  486         return deployerNames;
  487      }
  488   
  489      // ServiceMBeanSupport overrides ---------------------------------
  490   
  491      protected ObjectName getObjectName(MBeanServer server, ObjectName name)
  492         throws MalformedObjectNameException
  493      {
  494         return name == null ? OBJECT_NAME : name;
  495      }
  496   
  497      /**
  498       * The <code>createService</code> method is one of the ServiceMBean lifecyle operations.
  499       * (no jmx tag needed from superinterface)
  500       * @exception Exception if an error occurs
  501       */
  502      protected void createService() throws Exception
  503      {
  504         ServerConfig config = ServerConfigLocator.locate();
  505         // Get the temp directory location
  506         File basedir = config.getServerTempDir();
  507         // Set the local copy temp dir to tmp/deploy
  508         tempDir = new File(basedir, "deploy");
  509         // Delete any existing content
  510         Files.delete(tempDir);
  511         // Make sure the directory exists
  512         tempDir.mkdirs();
  513   
  514         // used in inLocalCopyDir
  515         tempDirString = tempDir.toURL().toString();
  516         
  517         // handles SuffixOrder & RelativeSuffixOrder attributes
  518         suffixOrderHelper.initialize();
  519      }
  520   
  521      /**
  522       * The <code>shutdown</code> method undeploys all deployed packages in
  523       * reverse order of their deployement.
  524       *
  525       * @jmx.managed-operation
  526       */
  527      public void shutdown()
  528      {
  529         // if we shutdown in the middle of a scan, it still might be possible that we try to redeploy
  530         // things we are busy killing...
  531         int deployCounter = 0;
  532   
  533         // undeploy everything in sight
  534         List copy;
  535         synchronized (deploymentList)
  536         {
  537            copy = new ArrayList(deploymentList);
  538         }
  539         for (ListIterator i = copy.listIterator(copy.size()); i.hasPrevious(); )
  540         {
  541            try
  542            {
  543               undeploy((DeploymentInfo)i.previous(), true);
  544               deployCounter++;
  545            }
  546            catch (Exception e)
  547            {
  548               log.info("exception trying to undeploy during shutdown", e);
  549            }
  550   
  551         }
  552         // Help GC
  553         this.deployers.clear();
  554         this.deploymentMap.clear();
  555         this.deploymentList.clear();
  556         this.waitingDeployments.clear();
  557         this.tempDir = null;
  558         
  559         log.debug("Undeployed " + deployCounter + " deployed packages");
  560      }
  561   
  562   
  563      /**
  564       * Describe <code>redeploy</code> method here.
  565       *
  566       * @param urlspec a <code>String</code> value
  567       * @exception DeploymentException if an error occurs
  568       * @exception MalformedURLException if an error occurs
  569       * @jmx.managed-operation
  570       */
  571      public void redeploy(String urlspec)
  572         throws DeploymentException, MalformedURLException
  573      {
  574         redeploy(new URL(urlspec));
  575      }
  576   
  577      /**
  578       * Describe <code>redeploy</code> method here.
  579       *
  580       * @param url an <code>URL</code> value
  581       * @exception DeploymentException if an error occurs
  582       * @jmx.managed-operation
  583       */
  584      public void redeploy(URL url) throws DeploymentException
  585      {
  586         undeploy(url);
  587         deploy(url);
  588      }
  589   
  590      /**
  591       * Describe <code>redeploy</code> method here.
  592       *
  593       * @param sdi a <code>DeploymentInfo</code> value
  594       * @exception DeploymentException if an error occurs
  595       * @jmx.managed-operation
  596       */
  597      public void redeploy(DeploymentInfo sdi) throws DeploymentException
  598      {
  599         try
  600         {
  601            undeploy(sdi);
  602         }
  603         catch (Throwable t)
  604         {
  605            log.info("Throwable from undeployment attempt: ", t);
  606         } // end of try-catch
  607         sdi.setServer(server);
  608         deploy(sdi);
  609      }
  610   
  611      /**
  612       * The <code>undeploy</code> method undeploys a package identified by a string
  613       * representation of a URL.
  614       *
  615       * @param urlspec the stringfied url to undeploy
  616       * @jmx.managed-operation
  617       */
  618      public void undeploy(String urlspec)
  619         throws DeploymentException, MalformedURLException
  620      {
  621         undeploy(new URL(urlspec));
  622      }
  623      
  624      /**
  625       * The <code>undeploy</code> method undeploys a package identified by a URL
  626       *
  627       * @param url the url to undeploy
  628       * @jmx.managed-operation
  629       */
  630      public void undeploy(URL url) throws DeploymentException
  631      {
  632         String deploymentName = contextMap.remove(url);
  633         if (deploymentName != null)
  634         {
  635            try
  636            {
  637               delegate.removeDeployment(deploymentName);
  638               delegate.process();
  639            }
  640            catch(Exception e)
  641            {
  642               DeploymentException ex = new DeploymentException("Error during undeploy of: "+url, e);
  643               throw ex;
  644            }
  645         }
  646         else
  647         {
  648            log.warn("undeploy '" + url + "' : package not deployed");
  649         }
  650      }
  651   
  652      /**
  653       * The <code>undeploy</code> method undeploys a package represented by a
  654       * DeploymentInfo object.
  655       *
  656       * @param di a <code>DeploymentInfo</code> value
  657       * @jmx.managed-operation
  658       */
  659      public void undeploy(DeploymentInfo di)
  660      {
  661         undeploy(di, false);
  662      }
  663      protected void undeploy(DeploymentInfo di, boolean isShutdown)
  664      {
  665         log.debug("Undeploying "+di.url);
  666         stop(di);
  667         destroy(di);
  668      }
  669   
  670      /**
  671       * The <code>stop</code> method  is the first internal step of undeployment
  672       *
  673       * @param di a <code>DeploymentInfo</code> value
  674       */
  675      private void stop(DeploymentInfo di)
  676      {
  677         // Stop all sub-deployments
  678         ArrayList reverseSortedSubs = new ArrayList(di.subDeployments);
  679         Collections.sort(reverseSortedSubs, infoSorter);
  680         Collections.reverse(reverseSortedSubs);
  681         for (Iterator subs = reverseSortedSubs.iterator(); subs.hasNext();)
  682         {
  683            DeploymentInfo sub = (DeploymentInfo) subs.next();
  684            log.debug("Stopping sub deployment: "+sub.url);
  685            stop(sub);
  686         }
  687         // Lastly stop this deployment itself
  688         try
  689         {
  690            // Tell the respective deployer to undeploy this one
  691            if (di.deployer != null)
  692            {
  693               di.deployer.stop(di);
  694               di.status="Stopped";
  695               di.state = DeploymentState.STOPPED;
  696            }
  697         }
  698         catch (Throwable t)
  699         {
  700            log.error("Deployer stop failed for: " + di.url, t);
  701         }
  702   
  703      }
  704   
  705      /**
  706       * The <code>destroy</code> method is the second and final internal undeployment step.
  707       *
  708       * @param di a <code>DeploymentInfo</code> value
  709       */
  710      private void destroy(DeploymentInfo di)
  711      {
  712         // Destroy all sub-deployments
  713         ArrayList reverseSortedSubs = new ArrayList(di.subDeployments);
  714         Collections.sort(reverseSortedSubs, infoSorter);
  715         Collections.reverse(reverseSortedSubs);
  716         for (Iterator subs = reverseSortedSubs.iterator(); subs.hasNext();)
  717         {
  718            DeploymentInfo sub = (DeploymentInfo) subs.next();
  719            log.debug("Destroying sub deployment: "+sub.url);
  720            destroy(sub);
  721         }
  722         // Lastly destroy the deployment itself
  723         try
  724         {
  725            // Tell the respective deployer to undeploy this one
  726            if (di.deployer != null)
  727            {
  728               di.deployer.destroy(di);
  729               di.status="Destroyed";
  730               di.state = DeploymentState.DESTROYED;
  731            }
  732         }
  733         catch (Throwable t)
  734         {
  735            log.error("Deployer destroy failed for: " + di.url, t);
  736            di.state = DeploymentState.FAILED;
  737         }
  738   
  739         try
  740         {
  741            // remove from local maps
  742            synchronized (deploymentList)
  743            {
  744               deploymentMap.remove(di.url);
  745               if (deploymentList.lastIndexOf(di) != -1)
  746               {
  747                  deploymentList.remove(deploymentList.lastIndexOf(di));
  748               }
  749            }
  750            synchronized (waitingDeployments)
  751            {
  752               waitingDeployments.remove(di);
  753            }
  754            // Nuke my stuff, this includes the class loader
  755            di.cleanup();
  756   
  757            log.debug("Undeployed "+di.url);
  758         }
  759         catch (Throwable t)
  760         {
  761            log.error("Undeployment cleanup failed: " + di.url, t);
  762         }
  763      }
  764   
  765      /**
  766       * The <code>deploy</code> method deploys a package identified by a
  767       * string representation of a URL.
  768       *
  769       * @param urlspec a <code>String</code> value
  770       * @exception MalformedURLException if an error occurs
  771       * @jmx.managed-operation
  772       */
  773      public void deploy(String urlspec)
  774         throws DeploymentException, MalformedURLException
  775      {
  776         if( server == null )
  777            throw new DeploymentException("The MainDeployer has been unregistered");
  778   
  779         URL url;
  780         try
  781         {
  782            url = new URL(urlspec);
  783         }
  784         catch (MalformedURLException e)
  785         {
  786            File file = new File(urlspec);
  787            url = file.toURL();
  788         }
  789   
  790         deploy(url);
  791      }
  792   
  793      /**
  794       * The <code>deploy</code> method deploys a package identified by a URL
  795       *
  796       * @param url an <code>URL</code> value
  797       * @jmx.managed-operation
  798       */
  799      public void deploy(URL url) throws DeploymentException
  800      {
  801         log.info("deploy, url="+url);
  802         String deploymentName = contextMap.get(url);
  803         // if it does not exist create a new deployment
  804         if (deploymentName == null)
  805         {
  806            try
  807            {
  808               VirtualFile file = VFS.getRoot(url);
  809               VFSDeployment deployment = deploymentFactory.createVFSDeployment(file);
  810               delegate.addDeployment(deployment);
  811               deploymentName = deployment.getName();
  812               delegate.process();
  813               // TODO: JBAS-4292
  814               contextMap.put(url, deploymentName);
  815               delegate.checkComplete(deployment);
  816            }
  817            catch(Exception e)
  818            {
  819               log.warn("Failed to deploy: "+url, e);
  820               DeploymentException ex = new DeploymentException("Failed to deploy: "+url, e);
  821               throw ex;
  822            }
  823         }
  824      }
  825   
  826      /**
  827       * The <code>deploy</code> method deploys a package represented by a DeploymentInfo object.
  828       *
  829       * @param deployment a <code>DeploymentInfo</code> value
  830       * @exception DeploymentException if an error occurs
  831       * @jmx.managed-operation
  832       */
  833      public void deploy(DeploymentInfo deployment)
  834         throws DeploymentException
  835      {
  836         // If we are already deployed return
  837         if (isDeployed(deployment.url))
  838         {
  839            log.info("Package: " + deployment.url + " is already deployed");
  840            return;
  841         }
  842         log.debug("Starting deployment of package: " + deployment.url);
  843   
  844         boolean inited = false;
  845         try
  846         {
  847            inited = init(deployment);
  848         }
  849         catch (Throwable t)
  850         {
  851            log.error("Could not initialise deployment: " + deployment.url, t);
  852            DeploymentException.rethrowAsDeploymentException("Could not initialise deployment: " + deployment.url, t);
  853         }
  854         if ( inited )
  855         {
  856            create(deployment);
  857            start(deployment);
  858            log.debug("Deployed package: " + deployment.url);
  859         } // end of if ()
  860         else
  861         {
  862            log.debug("Deployment of package: " + deployment.url + " is waiting for an appropriate deployer.");
  863         } // end of else
  864      }
  865   
  866   
  867      /**
  868       * The <code>init</code> method is the first internal deployment step.
  869       * The tasks are to copy the code if necessary,
  870       * set up classloaders, and identify the deployer for the package.
  871       *
  872       * @param deployment a <code>DeploymentInfo</code> value
  873       * @throws DeploymentException if an error occurs
  874       */
  875      private boolean init(DeploymentInfo deployment) throws DeploymentException
  876      {
  877         // If we are already deployed return
  878         if (isDeployed(deployment.url))
  879         {
  880            log.info("Package: " + deployment.url + " is already deployed");
  881            return false;
  882         }
  883         log.debug("Starting deployment (init step) of package at: " + deployment.url);
  884         try
  885         {
  886            // Create a local copy of that File, the sdi keeps track of the copy directory
  887            if (deployment.localUrl == null)
  888            {
  889               makeLocalCopy(deployment);
  890               URL[] localCl = new URL[]{deployment.localUrl};
  891               deployment.localCl = new URLClassLoader(localCl);
  892            }
  893   
  894            // What deployer is able to deploy this file
  895            findDeployer(deployment);
  896   
  897            if(deployment.deployer == null)
  898            {
  899               deployment.state = DeploymentState.INIT_WAITING_DEPLOYER;
  900               log.debug("deployment waiting for deployer: " + deployment.url);
  901               synchronized (waitingDeployments)
  902               {
  903                  if (waitingDeployments.contains(deployment) == false)
  904                     waitingDeployments.add(deployment);
  905               }
  906               return false;
  907            }
  908            deployment.state = DeploymentState.INIT_DEPLOYER;
  909            //we have the deployer, continue deployment.
  910            deployment.deployer.init(deployment);
  911            // initialize the unified classloaders for this deployment
  912            deployment.createClassLoaders();
  913            deployment.state = DeploymentState.INITIALIZED;
  914   
  915            // Add the deployment to the map so we can detect circular deployments
  916            synchronized (deploymentList)
  917            {
  918               deploymentMap.put(deployment.url, deployment);
  919            }
  920   
  921            // create subdeployments as needed
  922            parseManifestLibraries(deployment);
  923   
  924            log.debug("found " + deployment.subDeployments.size() + " subpackages of " + deployment.url);
  925            // get sorted subDeployments
  926            ArrayList sortedSubs = new ArrayList(deployment.subDeployments);
  927            Collections.sort(sortedSubs, infoSorter);
  928            for (Iterator lt = sortedSubs.listIterator(); lt.hasNext();)
  929            {
  930               init((DeploymentInfo) lt.next());
  931            }
  932         }
  933         catch (Exception e)
  934         {
  935            deployment.state = DeploymentState.FAILED;
  936            DeploymentException.rethrowAsDeploymentException("exception in init of " + deployment.url, e);
  937         }
  938         finally
  939         {
  940            // whether you do it or not, for the autodeployer
  941            try
  942            {
  943               URL url = deployment.localUrl == null ? deployment.url : deployment.localUrl;
  944   
  945               long lastModified = -1;
  946   
  947               if (url.getProtocol().equals("file"))
  948                  lastModified = new File(url.getFile()).lastModified();
  949               else
  950                  lastModified = url.openConnection().getLastModified();
  951   
  952               deployment.lastModified=lastModified;
  953               deployment.lastDeployed=System.currentTimeMillis();
  954            }
  955            catch (IOException ignore)
  956            {
  957               deployment.lastModified=System.currentTimeMillis();
  958               deployment.lastDeployed=System.currentTimeMillis();
  959            }
  960   
  961            synchronized (deploymentList)
  962            {
  963               // Do we watch it? Watch only urls outside our copy directory.
  964               if (!inLocalCopyDir(deployment.url) && deploymentList.contains(deployment) == false)
  965               {
  966                  deploymentList.add(deployment);
  967                  log.debug("Watching new file: " + deployment.url);
  968               }
  969            }
  970         }
  971         return true;
  972      }
  973   
  974      /**
  975       * The <code>create</code> method is the second internal deployment step.
  976       * It should set up all information not
  977       * requiring other components.  for instance, the ejb Container is created,
  978       * and the proxy bound into jndi.
  979       *
  980       * @param deployment a <code>DeploymentInfo</code> value
  981       * @throws DeploymentException if an error occurs
  982       */
  983      private void create(DeploymentInfo deployment) throws DeploymentException
  984      {
  985         log.debug("create step for deployment " + deployment.url);
  986         try
  987         {
  988            ArrayList sortedSubs = new ArrayList(deployment.subDeployments);
  989            Collections.sort(sortedSubs, infoSorter);
  990            for (Iterator lt = sortedSubs.listIterator(); lt.hasNext();)
  991            {
  992               create((DeploymentInfo) lt.next());
  993            }
  994            deployment.state = DeploymentState.CREATE_SUBDEPLOYMENTS;
  995   
  996            // Deploy this SDI, if it is a deployable type
  997            if (deployment.deployer != null)
  998            {
  999               try
 1000               {
 1001                  deployment.state = DeploymentState.CREATE_DEPLOYER;
 1002                  deployment.deployer.create(deployment);
 1003                  // See if all mbeans are created...
 1004                  deployment.state = DeploymentState.CREATED;
 1005                  deployment.status="Created";
 1006                  log.debug("Done with create step of deploying " + deployment.shortName);
 1007               }
 1008               catch (Throwable t)
 1009               {
 1010                  log.error("Could not create deployment: " + deployment.url, t);
 1011                  throw t;
 1012               }
 1013            }
 1014            else
 1015            {
 1016               log.debug("Still no deployer for package in create step: "  + deployment.shortName);
 1017            } // end of else
 1018         }
 1019         catch (Throwable t)
 1020         {
 1021            log.trace("could not create deployment: " + deployment.url, t);
 1022            deployment.status = "Deployment FAILED reason: " + t.getMessage();
 1023            deployment.state = DeploymentState.FAILED;
 1024            DeploymentException.rethrowAsDeploymentException("Could not create deployment: " + deployment.url, t);
 1025         }
 1026      }
 1027   
 1028      /**
 1029       * The <code>start</code> method is the third and final internal deployment step.
 1030       * The purpose is to set up relationships between components.
 1031       * for instance, ejb links are set up here.
 1032       *
 1033       * @param deployment a <code>DeploymentInfo</code> value
 1034       * @throws DeploymentException if an error occurs
 1035       */
 1036      private void start(DeploymentInfo deployment) throws DeploymentException
 1037      {
 1038         deployment.status = "Starting";
 1039         log.debug("Begin deployment start " + deployment.url);
 1040         try
 1041         {
 1042            ArrayList sortedSubs = new ArrayList(deployment.subDeployments);
 1043            Collections.sort(sortedSubs, infoSorter);
 1044            for (Iterator lt = sortedSubs.listIterator(); lt.hasNext();)
 1045            {
 1046               start((DeploymentInfo) lt.next());
 1047            }
 1048            deployment.state = DeploymentState.START_SUBDEPLOYMENTS;
 1049   
 1050            // Deploy this SDI, if it is a deployable type
 1051            if (deployment.deployer != null)
 1052            {
 1053               try
 1054               {
 1055                  deployment.state = DeploymentState.START_DEPLOYER;
 1056                  deployment.deployer.start(deployment);
 1057                  // See if all mbeans are started...
 1058                  Object[] args = {deployment, DeploymentState.STARTED};
 1059                  String[] sig = {"org.jboss.deployment.DeploymentInfo",
 1060                     "org.jboss.deployment.DeploymentState"};
 1061                  server.invoke(serviceController, "validateDeploymentState",args, sig);
 1062                  deployment.status = "Deployed";
 1063                  log.debug("End deployment start on package: "+ deployment.shortName);
 1064               }
 1065               catch (Throwable t)
 1066               {
 1067                  log.error("Could not start deployment: " + deployment.url, t);
 1068                  throw t;
 1069               }
 1070            }
 1071            else
 1072            {
 1073               log.debug("Still no deployer for package in start step: "  + deployment.shortName);
 1074            } // end of else
 1075         }
 1076         catch (Throwable t)
 1077         {
 1078            log.trace("could not start deployment: " + deployment.url, t);
 1079            deployment.state = DeploymentState.FAILED;
 1080            deployment.status = "Deployment FAILED reason: " + t.getMessage();
 1081            DeploymentException.rethrowAsDeploymentException("Could not create deployment: " + deployment.url, t);
 1082         }
 1083      }
 1084   
 1085      /**
 1086       * The <code>findDeployer</code> method attempts to find a deployer for the DeploymentInfo
 1087       * supplied as a parameter.
 1088       *
 1089       * @param sdi a <code>DeploymentInfo</code> value
 1090       */
 1091      private void findDeployer(DeploymentInfo sdi)
 1092      {
 1093         // If there is already a deployer use it
 1094         if( sdi.deployer != null )
 1095         {
 1096            log.debug("using existing deployer "+sdi.deployer);
 1097            return;
 1098         }
 1099   
 1100         //
 1101         // To deploy directories of beans one should just name the directory
 1102         // mybean.ear/bla...bla, so that the directory gets picked up by the right deployer
 1103         //
 1104         synchronized(deployers)
 1105         {
 1106            for (Iterator iterator = deployers.iterator(); iterator.hasNext(); )
 1107            {
 1108               SubDeployer deployer = (SubDeployer) iterator.next();
 1109               if (deployer.accepts(sdi))
 1110               {
 1111                  sdi.deployer = deployer;
 1112                  log.debug("using deployer "+deployer);
 1113                  return;
 1114               }
 1115            }
 1116         }
 1117         log.debug("No deployer found for url: " + sdi.url);
 1118      }
 1119   
 1120      /**
 1121       * The <code>parseManifestLibraries</code> method looks into the manifest for classpath
 1122       * goo, and tries to deploy referenced packages.
 1123       *
 1124       * @param sdi a <code>DeploymentInfo</code> value
 1125       */
 1126      private void parseManifestLibraries(DeploymentInfo sdi)
 1127      {
 1128         String classPath = null;
 1129   
 1130         Manifest mf = sdi.getManifest();
 1131   
 1132         if( mf != null )
 1133         {
 1134            Attributes mainAttributes = mf.getMainAttributes();
 1135            classPath = mainAttributes.getValue(Attributes.Name.CLASS_PATH);
 1136         }
 1137   
 1138         if (classPath != null)
 1139         {
 1140            StringTokenizer st = new StringTokenizer(classPath);
 1141            log.debug("resolveLibraries: "+classPath);
 1142   
 1143            while (st.hasMoreTokens())
 1144            {
 1145               URL lib = null;
 1146               String tk = st.nextToken();
 1147               log.debug("new manifest entry for sdi at "+sdi.shortName+" entry is "+tk);
 1148   
 1149               try
 1150               {
 1151                  if (sdi.isDirectory)
 1152                  {
 1153                     File parentDir = new File(sdi.url.getPath()).getParentFile();
 1154                     lib = new File(parentDir, tk).toURL();
 1155                  }
 1156                  else
 1157                  {
 1158                     lib = new URL(sdi.url, tk);
 1159                  }
 1160   
 1161                  // Only deploy this if it is not already being deployed
 1162                  if ( deploymentMap.containsKey(lib) == false )
 1163                  {
 1164                     /* Test that the only deployer for this is the JARDeployer.
 1165                      Any other type of deployment cannot be initiated through
 1166                      a manifest reference.
 1167                     */
 1168                     DeploymentInfo mfRef = new DeploymentInfo(lib, null, getServer());
 1169                     makeLocalCopy(mfRef);
 1170                     URL[] localURL = {mfRef.localUrl};
 1171                     mfRef.localCl = new java.net.URLClassLoader(localURL);
 1172                     findDeployer(mfRef);
 1173                     SubDeployer deployer = mfRef.deployer;
 1174                     if(deployer != null && (deployer instanceof JARDeployer) == false)
 1175                     {
 1176                        // Its a non-jar deployment that must be deployed seperately
 1177                        log.warn("Found non-jar deployer for " + tk + ": " + deployer);
 1178                     }
 1179   
 1180                     // add the library
 1181                     sdi.addLibraryJar(lib);
 1182                  }
 1183               }
 1184               catch (Exception ignore)
 1185               {
 1186                  log.debug("The manifest entry in "+sdi.url+" references URL "+lib+
 1187                     " which could not be opened, entry ignored", ignore);
 1188               }
 1189            }
 1190         }
 1191      }
 1192   
 1193      /**
 1194       * Downloads the jar file or directory the src URL points to.
 1195       * In case of directory it becomes packed to a jar file.
 1196       */
 1197      private void makeLocalCopy(DeploymentInfo sdi)
 1198      {
 1199         try
 1200         {
 1201            if (sdi.url.getProtocol().equals("file") && (!copyFiles || sdi.isDirectory))
 1202            {
 1203               // If local copies have been disabled, do nothing
 1204               sdi.localUrl = sdi.url;
 1205               return;
 1206            }
 1207            // Are we already in the localCopyDir?
 1208            else if (inLocalCopyDir(sdi.url))
 1209            {
 1210               sdi.localUrl = sdi.url;
 1211               return;
 1212            }
 1213            else
 1214            {
 1215               String shortName = sdi.shortName;
 1216               File localFile = File.createTempFile("tmp", shortName, tempDir);
 1217               sdi.localUrl = localFile.toURL();
 1218               copy(sdi.url, localFile);
 1219            }
 1220         }
 1221         catch (Exception e)
 1222         {
 1223            log.error("Could not make local copy for " + sdi.url, e);
 1224         }
 1225      }
 1226   
 1227      private boolean inLocalCopyDir(URL url)
 1228      {
 1229         int i = 0;
 1230         String urlTest = url.toString();
 1231         if( urlTest.startsWith("jar:") )
 1232            i = 4;
 1233   
 1234         return urlTest.startsWith(tempDirString, i);
 1235      }
 1236   
 1237      protected void copy(URL src, File dest) throws IOException
 1238      {
 1239         log.debug("Copying " + src + " -> " + dest);
 1240         
 1241         // Validate that the dest parent directory structure exists
 1242         File dir = dest.getParentFile();
 1243         if (!dir.exists())
 1244         {
 1245            boolean created = dir.mkdirs();
 1246            if( created == false )
 1247               throw new IOException("mkdirs failed for: "+dir.getAbsolutePath());
 1248         }
 1249   
 1250         // Remove any existing dest content
 1251         if( dest.exists() == true )
 1252         {
 1253            boolean deleted = Files.delete(dest);
 1254            if( deleted == false )
 1255               throw new IOException("delete of previous content failed for: "+dest.getAbsolutePath());
 1256         }
 1257   
 1258         if (src.getProtocol().equals("file"))
 1259         {
 1260            File srcFile = new File(src.getFile());
 1261            if (srcFile.isDirectory())
 1262            {
 1263               log.debug("Making zip copy of: " + srcFile);
 1264               // make a jar archive of the directory
 1265               OutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
 1266               JarUtils.jar(out, srcFile.listFiles());
 1267               out.close();
 1268               return;
 1269            }
 1270         }
 1271   
 1272         InputStream in = new BufferedInputStream(src.openStream());
 1273         OutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
 1274         Streams.copy(in, out);
 1275         out.flush();
 1276         out.close();
 1277         in.close();
 1278      }
 1279   
 1280      /**
 1281       * The <code>start</code> method starts a package identified by a URL
 1282       *
 1283       * @param urlspec an <code>URL</code> value
 1284       * @jmx.managed-operation
 1285       */
 1286      public void start(String urlspec)
 1287         throws DeploymentException, MalformedURLException
 1288      {
 1289         throw new DeploymentException("Not supported");
 1290      }
 1291   
 1292      /**
 1293       * The <code>stop</code> method stops a package identified by a URL
 1294       *
 1295       * @param urlspec an <code>URL</code> value
 1296       * @jmx.managed-operation
 1297       */
 1298      public void stop(String urlspec)
 1299         throws DeploymentException, MalformedURLException
 1300      {	
 1301         throw new DeploymentException("Not supported");
 1302      }
 1303   
 1304      /**
 1305       * The <code>isDeployed</code> method tells you if a package identified by a string
 1306       * representation of a URL is currently deployed.
 1307       *
 1308       * @param url a <code>String</code> value
 1309       * @return a <code>boolean</code> value
 1310       * @exception MalformedURLException if an error occurs
 1311       * @jmx.managed-operation
 1312       */
 1313      public boolean isDeployed(String url)
 1314         throws MalformedURLException
 1315      {
 1316         return isDeployed(new URL(url));
 1317      }
 1318   
 1319      /**
 1320       * The <code>isDeployed</code> method tells you if a packaged identified by
 1321       * a URL is deployed.
 1322       * @param url an <code>URL</code> value
 1323       * @return a <code>boolean</code> value
 1324       * @jmx.managed-operation
 1325       */
 1326      public boolean isDeployed(URL url)
 1327      {
 1328         String name = contextMap.get(url);
 1329         if (name == null)
 1330         {
 1331            if (log.isTraceEnabled())
 1332               log.trace("No such context: " + url);
 1333            if (url == null)
 1334               throw new IllegalArgumentException("Null url");
 1335            String urlString = url.toString();
 1336            // remove this once the JBoss-test is updated with VFS usage
 1337            if (urlString.startsWith("vfs") == false)
 1338               return checkDeployed("vfs" + urlString);
 1339            else
 1340               return checkDeployed(urlString);
 1341         }
 1342   
 1343         return checkDeployed(name);
 1344      }
 1345   
 1346      /**
 1347       * Is deployed.
 1348       *
 1349       * @param name the name of the deployment
 1350       * @return true if deployed, false otherwise 
 1351       */
 1352      protected boolean checkDeployed(String name)
 1353      {
 1354         org.jboss.deployers.spi.DeploymentState deploymentState = delegate.getDeploymentState(name);
 1355         log.debug("isDeployed, url="+name+", state="+deploymentState);
 1356         return deploymentState == org.jboss.deployers.spi.DeploymentState.DEPLOYED;
 1357      }
 1358   
 1359      /**
 1360       * The <code>getDeployment</code> method returns the Deployment
 1361       * object for the URL supplied.
 1362       *
 1363       * @param url an <code>URL</code> value
 1364       * @return a <code>Deployment</code> value
 1365       * @jmx.managed-operation
 1366       */
 1367      public Deployment getDeployment(URL url)
 1368      {
 1369         String name = contextMap.get(url);
 1370         if (name == null)
 1371            return null;
 1372   
 1373         Deployment dc = delegate.getDeployment(name);
 1374         log.debug("getDeployment, url="+url+", dc="+dc);
 1375         return dc;
 1376      }
 1377   
 1378      /**
 1379       * The <code>getDeploymentContext</code> method returns the DeploymentContext
 1380       * object for the URL supplied.
 1381       *
 1382       * @param url an <code>URL</code> value
 1383       * @return a <code>DeploymentContext</code> value
 1384       * @jmx.managed-operation
 1385       */
 1386      @Deprecated
 1387      public DeploymentContext getDeploymentContext(URL url)
 1388      {
 1389         String name = contextMap.get(url);
 1390         if (name == null)
 1391            return null;
 1392   
 1393         MainDeployerStructure structure = (MainDeployerStructure) delegate;
 1394         DeploymentContext dc = structure.getDeploymentContext(name);
 1395         log.debug("getDeploymentContext, url="+url+", dc="+dc);
 1396         return dc;
 1397      }
 1398   
 1399      /**
 1400       * The <code>getDeploymentUnit</code> method returns the DeploymentUnit
 1401       * object for the URL supplied.
 1402       *
 1403       * @param url an <code>URL</code> value
 1404       * @return a <code>DeploymentUnit</code> value
 1405       * @jmx.managed-operation
 1406       */
 1407      public DeploymentUnit getDeploymentUnit(URL url)
 1408      {
 1409         String name = contextMap.get(url);
 1410         if (name == null)
 1411            return null;
 1412   
 1413         MainDeployerStructure structure = (MainDeployerStructure) delegate;
 1414         DeploymentUnit du = structure.getDeploymentUnit(name);
 1415         log.debug("getDeploymentUnit, url="+url+", du="+du);
 1416         return du;
 1417      }
 1418   
 1419      /**
 1420       * The <code>getWatchUrl</code> method returns the URL that, when modified,
 1421       * indicates that a redeploy is needed.
 1422       *
 1423       * @param url an <code>URL</code> value
 1424       * @return a <code>URL</code> value
 1425       * @jmx.managed-operation
 1426       */
 1427      public URL getWatchUrl(URL url)
 1428      {
 1429         return url;
 1430      }
 1431   
 1432      /** Check the current deployment states and generate a IncompleteDeploymentException
 1433       * if there are mbeans waiting for depedencies.
 1434       * @exception IncompleteDeploymentException
 1435       * @jmx.managed-operation
 1436       */
 1437      public void checkIncompleteDeployments() throws DeploymentException
 1438      {
 1439         try
 1440         {
 1441            delegate.checkComplete();
 1442         }
 1443         catch (Exception e)
 1444         {
 1445            throw new DeploymentException("Deployments are incomplete", e);
 1446         }
 1447      }
 1448   
 1449      /**
 1450       * @param parent
 1451       * @param map
 1452       */
 1453      private void fillParentAndChildrenSDI(DeploymentInfo parent, Map map)
 1454      {
 1455         Set subDeployments = parent.subDeployments;      
 1456         Iterator it = subDeployments.iterator();
 1457         while (it.hasNext())
 1458         {
 1459            DeploymentInfo child = (DeploymentInfo) it.next();
 1460            SerializableDeploymentInfo sdichild = returnSDI(child, map);      
 1461            sdichild.parent = returnSDI(parent, map);
 1462            sdichild.parent.subDeployments.add(sdichild);
 1463            fillParentAndChildrenSDI(child, map);
 1464         }
 1465      }
 1466   
 1467      private SerializableDeploymentInfo returnSDI(DeploymentInfo di, Map map)
 1468      {
 1469          SerializableDeploymentInfo sdi = (SerializableDeploymentInfo) map.get(di.url);
 1470          if( sdi == null )
 1471          {
 1472              sdi = new SerializableDeploymentInfo(di);
 1473              map.put(di.url, sdi);                
 1474           }
 1475          return sdi;
 1476      }
 1477   }

Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » deployment » [javadoc | source]