[jboss-cvs] JBossAS SVN: r108072 - trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Sep 9 11:01:44 EDT 2010


Author: flavia.rainone at jboss.com
Date: 2010-09-09 11:01:44 -0400 (Thu, 09 Sep 2010)
New Revision: 108072

Added:
   trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/ArchiveLoader.java
Modified:
   trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/Archive.java
   trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/DeploymentImpl.java
Log:
[JBAS-8250] Fix the problem on DeploymentImpl regarding cleanup of loaded BDAs


Modified: trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/Archive.java
===================================================================
--- trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/Archive.java	2010-09-09 14:59:12 UTC (rev 108071)
+++ trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/Archive.java	2010-09-09 15:01:44 UTC (rev 108072)
@@ -281,14 +281,14 @@
     */
    public void undeploy()
    {
+      synchronized(instances)
+      {
+         instances.remove(this.classLoader);
+      }
       for (ArchiveLifecycleListener listener: lifecycleListeners)
       {
          listener.archiveDestroyed(this);
       }
-      synchronized(instances)
-      {
-         instances.remove(this.classLoader);
-      }
    }
 
    @Override

Added: trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/ArchiveLoader.java
===================================================================
--- trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/ArchiveLoader.java	                        (rev 0)
+++ trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/ArchiveLoader.java	2010-09-09 15:01:44 UTC (rev 108072)
@@ -0,0 +1,152 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.weld.integration.deployer.env.bda;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.jboss.weld.ejb.spi.EjbDescriptor;
+
+/**
+ * An archive can either be loaded or deployed.
+ * Deployed archives are part of a DeploymentImpl, and will be automatically
+ * undeployed when the corresponding DeploymentImpl is removed from the
+ * system.
+ * Loaded archives are archives that are created for the sole purpose of
+ * fulfilling {code {@link DeploymentImpl#loadBeanDeploymentArchive(Class)}
+ * calls.
+ * 
+ * The ArchiveLoader loads those archives and keeps track of which
+ * DeploymentImpl instances required them being loaded, so that it can be
+ * determined when a loaded archive is no longer in use and can be safely
+ * undeployed.
+ * 
+ * @author <a href="mailto:flavia.rainone at jboss.com">Flavia Rainone</a>
+ * @version $Revision$
+ * @see DeploymentImpl#loadBeanDeploymentArchive(Class)
+ */
+class ArchiveLoader
+{
+   private Map<Archive, Collection<DeploymentImpl>> loadedArchives;
+
+   /**
+    * Constructor.
+    */
+   public ArchiveLoader()
+   {
+      loadedArchives = new HashMap<Archive, Collection<DeploymentImpl>>();
+   }
+
+   /**
+    * Loads an archive that contains {@code beanClass}.
+    * If such archive already exists, no archive is created and the
+    * preexistent one is returned.
+    * 
+    * @param beanClass  the class the loaded archive should contain
+    * @param deployment the deployment making this request
+    * @return  the requested Archive
+    */
+   public Archive load(Class<?> beanClass, DeploymentImpl deployment)
+   {
+      ClassLoader beanClassLoader = SecurityActions.getClassLoader(beanClass);
+      synchronized(beanClassLoader)
+      {
+         Archive archive = Archive.getInstance(beanClassLoader);
+         if (archive == null)
+         {
+            ArchiveInfo archiveInfo = new ArchiveInfo(beanClassLoader);
+            Collection<EjbDescriptor<?>> ejbs = Collections.emptyList();
+            archive = ArchiveFactory.createArchive(archiveInfo, ejbs);
+            registerArchiveLoadedByDeployment(archive, deployment);
+         }
+         else if (isLoaded(archive))
+         {
+            registerArchiveReloadedByDeployment(archive, deployment);
+         }
+         return archive;
+      }
+   }
+
+   /**
+    * Notifies this ArchiveLoader that the loaded {@code archive} is no longer
+    * being used by {@code deployment}, which should occur when {@code deployment}
+    * is being undeployed.
+    * 
+    * @param archive    an archive
+    * @param deployment the deployment being undeployed 
+    * @return  {@code true} if this archive is free to be released, i.e.,
+    *                       if it is not in use by any other deployment.
+    * @see DeploymentImpl#undeploy()
+    */
+   public boolean unload(Archive archive, DeploymentImpl deployment)
+   {
+      // this archive is not a loaded archive and hence cannot be undeployed
+      // as a loaded archive
+      if (!loadedArchives.containsKey(archive))
+      {
+         return false;
+      }
+      synchronized(archive.getClassLoader())
+      {
+         Collection<DeploymentImpl> deployments = loadedArchives.get(archive);
+         deployments.remove(deployment);
+         if (deployments.isEmpty())
+         {
+            loadedArchives.remove(archive);
+            return true;
+         }
+         return false;
+      }
+   }
+
+   /**
+    * Indicates whether {@code archive} is loaded by this ArchiveLoader.
+    */
+   private boolean isLoaded(Archive archive)
+   {
+      return loadedArchives.containsKey(archive);
+   }
+
+   /**
+    * Record that the loaded {@code archive} is being requested by
+    * {@code deployment}
+    */
+   private void registerArchiveReloadedByDeployment(Archive archive, DeploymentImpl deployment)
+   {
+      Collection<DeploymentImpl> deployments = loadedArchives.get(archive);
+      deployments.add(deployment);
+   }
+
+   /**
+    * Record that the newly created {@code archive} was requested by
+    * {@code deployment}.
+    */
+   private void registerArchiveLoadedByDeployment(Archive archive, DeploymentImpl deployment)
+   {
+      Collection<DeploymentImpl> deployments = new HashSet<DeploymentImpl>();
+      deployments.add(deployment);
+      loadedArchives.put(archive, deployments);
+   }
+}
\ No newline at end of file


Property changes on: trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/ArchiveLoader.java
___________________________________________________________________
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Modified: trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/DeploymentImpl.java
===================================================================
--- trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/DeploymentImpl.java	2010-09-09 14:59:12 UTC (rev 108071)
+++ trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/env/bda/DeploymentImpl.java	2010-09-09 15:01:44 UTC (rev 108072)
@@ -21,8 +21,8 @@
  */
 package org.jboss.weld.integration.deployer.env.bda;
 
-import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.Iterator;
 
 import javax.enterprise.inject.spi.Extension;
@@ -45,6 +45,8 @@
  */
 public class DeploymentImpl implements Deployment
 {
+   private static ArchiveLoader archiveLoader = new ArchiveLoader();
+   
    // the name of this deployment
    private String name;
 
@@ -85,6 +87,7 @@
          archives.add(ArchiveFactory.createArchive(archiveInfo, ejbs));
       }
       this.loadedBDAServiceRegistry = new ServiceRegistryFactory(ejbServicesFactory);
+      this.loadedArchives = new HashSet<Archive>();
    }
 
    public void initialize(Bootstrap bootstrap)
@@ -111,25 +114,8 @@
 
    public BeanDeploymentArchive loadBeanDeploymentArchive(Class<?> beanClass)
    {
-      ClassLoader beanClassLoader = SecurityActions.getClassLoader(beanClass);
-      Archive archive = Archive.getInstance(beanClassLoader);
-      if (archive == null)
-      {
-         synchronized(beanClassLoader)
-         {
-            archive = Archive.getInstance(beanClassLoader);
-            if (archive == null)
-            {
-               ArchiveInfo archiveInfo = new ArchiveInfo(beanClassLoader);
-               archive = ArchiveFactory.createArchive(archiveInfo, new ArrayList<EjbDescriptor<?>>());
-               if (loadedArchives == null)
-               {
-                  loadedArchives = new ArrayList<Archive>();
-               }
-               loadedArchives.add(archive);
-            }
-         }
-      }
+      Archive archive = archiveLoader.load(beanClass, this);
+      loadedArchives.add(archive);
       archive.addClass(beanClass);
       BeanDeploymentArchive bda = archive.getBeanDeploymentArchive();
       if (archive.getBeanDeploymentArchive() == null)
@@ -165,13 +151,17 @@
          iterator.remove();
          archive.undeploy();
       }
-      if (loadedArchives != null)
+      for (Archive archive: loadedArchives)
       {
-         for (Archive archive: loadedArchives)
+         // avoid a race condition where archiveLoader gives an ok to undeploy
+         // the archive while another thread executing archiveLoader.load
+         // retrieves the same archive
+         synchronized(archive.getClassLoader())
          {
-            // FIXME this does not work ok... what if the loaded Archive is being
-            // used by some other dpeloyment???
-            archive.undeploy();
+            if (archiveLoader.unload(archive, this))
+            {
+               archive.undeploy();
+            }
          }
       }
    }



More information about the jboss-cvs-commits mailing list