[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