diff --git a/container-api/src/main/java/org/jboss/forge/furnace/addons/AddonDependency.java b/container-api/src/main/java/org/jboss/forge/furnace/addons/AddonDependency.java index e2f4298d..4b2e215a 100644 --- a/container-api/src/main/java/org/jboss/forge/furnace/addons/AddonDependency.java +++ b/container-api/src/main/java/org/jboss/forge/furnace/addons/AddonDependency.java @@ -6,7 +6,6 @@ */ package org.jboss.forge.furnace.addons; -import org.jboss.forge.furnace.versions.Version; /** * An edge in the registered {@link Addon} graph. @@ -15,21 +14,11 @@ */ public interface AddonDependency { - /** - * Get the {@link Addon} dependent on the {@link Addon} returned by {@link #getDependency()}. - */ - public Addon getDependent(); - /** * Get the {@link Addon} dependency of the {@link Addon} returned by {@link #getDependent()}. */ public Addon getDependency(); - /** - * Return the {@link Version} of which the {@link Addon} returned by {@link #getDependency()} must be included. - */ - public Version getDependencyVersion(); - /** * Return true if the {@link Addon} dependency returned by {@link #getDependency()} is exported by the * dependent {@link Addon}. If the dependency is not exported, return false. diff --git a/container-tests/src/test/java/org/jboss/forge/furnace/views/MultipleRepositoryViewTest.java b/container-tests/src/test/java/org/jboss/forge/furnace/views/MultipleRepositoryViewTest.java index f2626946..8cb57110 100644 --- a/container-tests/src/test/java/org/jboss/forge/furnace/views/MultipleRepositoryViewTest.java +++ b/container-tests/src/test/java/org/jboss/forge/furnace/views/MultipleRepositoryViewTest.java @@ -10,13 +10,11 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; -import org.jboss.forge.addon.convert.ConverterFactory; import org.jboss.forge.addon.manager.AddonManager; import org.jboss.forge.addon.manager.impl.AddonManagerImpl; import org.jboss.forge.addon.maven.dependencies.FileResourceFactory; import org.jboss.forge.addon.maven.dependencies.MavenContainer; import org.jboss.forge.addon.maven.dependencies.MavenDependencyResolver; -import org.jboss.forge.addon.resource.DirectoryResource; import org.jboss.forge.arquillian.ConfigurationScanListener; import org.jboss.forge.furnace.Furnace; import org.jboss.forge.furnace.addons.Addon; @@ -25,7 +23,6 @@ import org.jboss.forge.furnace.repositories.AddonRepository; import org.jboss.forge.furnace.repositories.AddonRepositoryMode; import org.jboss.forge.furnace.se.ForgeFactory; -import org.jboss.forge.furnace.services.ExportedInstance; import org.jboss.forge.furnace.spi.ContainerLifecycleListener; import org.jboss.forge.furnace.spi.ListenerRegistration; import org.jboss.forge.furnace.util.Addons; @@ -60,7 +57,7 @@ public void teardown() } @Test - public void testAddonsCanBeSharedBetweenViews() throws IOException, InterruptedException + public void testAddonsSharedIfSubgraphEquivalent() throws IOException, InterruptedException { Furnace furnace = ForgeFactory.getInstance(Furnace.class.getClassLoader()); AddonRepository left = furnace.addRepository(AddonRepositoryMode.MUTABLE, repodir1); @@ -121,7 +118,7 @@ public void testAddonsCanBeSharedBetweenViews() throws IOException, InterruptedE } @Test - public void testAddonsDontFailIfDuplicatedInOtherRepositories() throws IOException, Exception + public void testAddonsDuplicatedIfSubgraphDiffers() throws IOException, InterruptedException { Furnace furnace = ForgeFactory.getInstance(Furnace.class.getClassLoader()); AddonRepository left = furnace.addRepository(AddonRepositoryMode.MUTABLE, repodir1); @@ -131,43 +128,59 @@ public void testAddonsDontFailIfDuplicatedInOtherRepositories() throws IOExcepti new MavenContainer()); AddonManager manager = new AddonManagerImpl(furnace, resolver); - AddonId facets = AddonId.from("org.jboss.forge.addon:facets", "2.0.0-SNAPSHOT"); - AddonId convert = AddonId.from("org.jboss.forge.addon:convert", "2.0.0-SNAPSHOT"); - AddonId resources = AddonId.from("org.jboss.forge.addon:resources", "2.0.0-SNAPSHOT"); + AddonId facets = AddonId.from("org.jboss.forge.addon:facets", "2.0.0.Alpha5"); + AddonId convert = AddonId.from("org.jboss.forge.addon:convert", "2.0.0.Alpha5"); + AddonId resources = AddonId.from("org.jboss.forge.addon:resources", "2.0.0.Alpha5"); + AddonId dependencies = AddonId.from("org.jboss.forge.addon:dependencies", "2.0.0.Alpha5"); + + AddonId facets6 = AddonId.from("org.jboss.forge.addon:facets", "2.0.0.Alpha6"); + Assert.assertFalse(left.isDeployed(dependencies)); Assert.assertFalse(left.isDeployed(resources)); Assert.assertFalse(left.isDeployed(facets)); + Assert.assertFalse(left.isDeployed(facets6)); Assert.assertFalse(left.isDeployed(convert)); + Assert.assertFalse(right.isDeployed(dependencies)); Assert.assertFalse(right.isDeployed(resources)); Assert.assertFalse(right.isDeployed(facets)); + Assert.assertFalse(right.isDeployed(facets6)); Assert.assertFalse(right.isDeployed(convert)); manager.install(facets).perform(left); manager.install(convert).perform(left); manager.install(resources).perform(left); - manager.install(resources).perform(right); + manager.install(dependencies).perform(left); - Assert.assertFalse(right.isDeployed(facets)); - Assert.assertFalse(right.isDeployed(convert)); - Assert.assertTrue(left.isDeployed(resources)); + manager.install(facets6).perform(right); + + Assert.assertTrue(left.isDeployed(facets)); Assert.assertTrue(left.isDeployed(convert)); Assert.assertTrue(left.isDeployed(resources)); - Assert.assertTrue(right.isDeployed(resources)); + Assert.assertTrue(left.isDeployed(dependencies)); + Assert.assertFalse(left.isDeployed(facets6)); + + Assert.assertFalse(right.isDeployed(facets)); + Assert.assertFalse(right.isDeployed(convert)); + Assert.assertFalse(right.isDeployed(resources)); + Assert.assertFalse(right.isDeployed(dependencies)); + Assert.assertTrue(right.isDeployed(facets6)); furnace.startAsync(); - Addons.waitUntilStarted(furnace.getAddonRegistry().getAddon(resources), 10, TimeUnit.SECONDS); - Addons.waitUntilStarted(furnace.getAddonRegistry().getAddon(facets), 10, TimeUnit.SECONDS); - Addons.waitUntilStarted(furnace.getAddonRegistry().getAddon(convert), 10, TimeUnit.SECONDS); + ConfigurationScanListener listener = new ConfigurationScanListener(); + ListenerRegistration registration = furnace.addContainerLifecycleListener(listener); + + while (!listener.isConfigurationScanned()) + Thread.sleep(100); + + AddonRegistry registry = furnace.getAddonRegistry(); + Addons.waitUntilStarted(registry.getAddon(resources), 10, TimeUnit.SECONDS); + AddonRegistry leftRegistry = furnace.getAddonRegistry(left); - System.out.println("Getting instances."); - ExportedInstance instance = furnace.getAddonRegistry() - .getExportedInstance(ConverterFactory.class); - ConverterFactory factory = instance.get(); + Addon addon = leftRegistry.getAddon(facets); + Assert.assertNotNull(addon); - factory.getConverter(File.class, - furnace.getAddonRegistry().getAddon(resources).getClassLoader() - .loadClass(DirectoryResource.class.getName())); + registration.removeListener(); furnace.stop(); } diff --git a/container/src/main/java/org/jboss/forge/furnace/FurnaceImpl.java b/container/src/main/java/org/jboss/forge/furnace/FurnaceImpl.java index 6d701e76..ab3f8a9e 100644 --- a/container/src/main/java/org/jboss/forge/furnace/FurnaceImpl.java +++ b/container/src/main/java/org/jboss/forge/furnace/FurnaceImpl.java @@ -14,7 +14,6 @@ import java.util.List; import java.util.Map; import java.util.ServiceLoader; -import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -30,7 +29,6 @@ import org.jboss.forge.furnace.spi.ContainerLifecycleListener; import org.jboss.forge.furnace.spi.ListenerRegistration; import org.jboss.forge.furnace.util.Assert; -import org.jboss.forge.furnace.util.Sets; import org.jboss.forge.furnace.versions.Version; import org.jboss.modules.Module; import org.jboss.modules.log.StreamModuleLogger; @@ -56,7 +54,6 @@ public class FurnaceImpl implements Furnace private Map lastRepoVersionSeen = new HashMap(); private final LockManager lock = new LockManagerImpl(); - private final Set views = Sets.getConcurrentSet(); private String[] args; @@ -141,7 +138,7 @@ public Furnace start(ClassLoader loader) do { boolean dirty = false; - if (!manager.isStartingAddons(views)) + if (!manager.isStartingAddons()) { for (AddonRepository repository : repositories) { @@ -159,7 +156,7 @@ public Furnace start(ClassLoader loader) try { fireBeforeConfigurationScanEvent(); - manager.forceUpdate(views); + manager.forceUpdate(); fireAfterConfigurationScanEvent(); } catch (Exception e) @@ -172,7 +169,7 @@ public Furnace start(ClassLoader loader) } while (alive && serverMode); - while (alive && manager.isStartingAddons(views)) + while (alive && manager.isStartingAddons()) { Thread.sleep(100); } @@ -269,50 +266,26 @@ public AddonRegistry getAddonRegistry(AddonRepository... repositories) { assertIsAlive(); - AddonRegistry result = findView(repositories); + AddonRegistry result = manager.findView(repositories); if (result == null) { if (repositories == null || repositories.length == 0) { result = new AddonRegistryImpl(lock, manager, getRepositories(), "ROOT"); - views.add(result); + manager.addView(result); } else { result = new AddonRegistryImpl(lock, manager, Arrays.asList(repositories), String.valueOf(registryCount++)); - views.add(result); - manager.forceUpdate(views); + manager.addView(result); + manager.forceUpdate(); } } return result; } - private AddonRegistry findView(AddonRepository... repositories) - { - AddonRegistry result = null; - - for (AddonView view : views) - { - Set viewRepositories = view.getRepositories(); - if (repositories == null || repositories.length == 0) - { - if (viewRepositories.containsAll(getRepositories()) && getRepositories().containsAll(viewRepositories)) - result = (AddonRegistry) view; - } - else if (viewRepositories.containsAll(Arrays.asList(repositories)) - && Arrays.asList(repositories).containsAll(viewRepositories)) - { - result = (AddonRegistry) view; - } - - if (result != null) - break; - } - return result; - } - public void disposeAddonView(AddonView view) { assertIsAlive(); @@ -321,12 +294,8 @@ public void disposeAddonView(AddonView view) throw new IllegalArgumentException( "Cannot dispose the root AddonRegistry. Call .stop() instead."); - if (!views.contains(view)) - throw new IllegalArgumentException("The given AddonRegistry does not belong to this Furnace instance."); - - views.remove(view); - - manager.forceUpdate(views); + manager.removeView(view); + manager.forceUpdate(); } @Override @@ -402,7 +371,7 @@ public ContainerStatus getStatus() if (!alive) return ContainerStatus.STOPPED; - boolean startingAddons = manager.isStartingAddons(views); + boolean startingAddons = manager.isStartingAddons(); return startingAddons ? ContainerStatus.STARTING : status; } @@ -416,11 +385,6 @@ public AddonLifecycleManager getAddonLifecycleManager() return manager; } - public Set getViews() - { - return views; - } - @Override public String toString() { diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/AddonDependencyImpl.java b/container/src/main/java/org/jboss/forge/furnace/addons/AddonDependencyImpl.java index ebc301a3..a9562abf 100644 --- a/container/src/main/java/org/jboss/forge/furnace/addons/AddonDependencyImpl.java +++ b/container/src/main/java/org/jboss/forge/furnace/addons/AddonDependencyImpl.java @@ -6,63 +6,40 @@ */ package org.jboss.forge.furnace.addons; -import org.jboss.forge.furnace.addons.Addon; -import org.jboss.forge.furnace.addons.AddonDependency; import org.jboss.forge.furnace.lock.LockManager; import org.jboss.forge.furnace.util.Assert; -import org.jboss.forge.furnace.versions.Version; /** * An edge in the registered {@link Addon} graph. - * + * * @author Lincoln Baxter, III */ public class AddonDependencyImpl implements AddonDependency { - private final Addon dependent; - private boolean exported = false; private boolean optional = false; private Addon dependency; - private Version dependencyVersion; @SuppressWarnings("unused") private LockManager lockManager; - public AddonDependencyImpl(LockManager lockManager, - Addon dependent, Version dependencyVersion, Addon dependency, boolean exported, boolean optional) + public AddonDependencyImpl(LockManager lockManager, Addon dependency, boolean exported, boolean optional) { Assert.notNull(lockManager, "LockManager must not be null."); - Assert.notNull(dependent, "Dependent Addon must not be null."); - Assert.notNull(dependencyVersion, "VersionRange must not be null."); Assert.notNull(dependency, "Dependency Addon not be null."); this.lockManager = lockManager; - this.dependent = dependent; - this.dependencyVersion = dependencyVersion; this.dependency = dependency; this.exported = exported; this.optional = optional; } - @Override - public Addon getDependent() - { - return dependent; - } - @Override public Addon getDependency() { return dependency; } - @Override - public Version getDependencyVersion() - { - return dependencyVersion; - } - @Override public boolean isExported() { diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/AddonImpl.java b/container/src/main/java/org/jboss/forge/furnace/addons/AddonImpl.java index 732360a1..ad20e9c9 100644 --- a/container/src/main/java/org/jboss/forge/furnace/addons/AddonImpl.java +++ b/container/src/main/java/org/jboss/forge/furnace/addons/AddonImpl.java @@ -6,72 +6,29 @@ */ package org.jboss.forge.furnace.addons; -import java.util.Collections; import java.util.Set; import java.util.concurrent.Future; -import org.jboss.forge.furnace.lock.LockManager; -import org.jboss.forge.furnace.modules.AddonModuleLoader; import org.jboss.forge.furnace.repositories.AddonRepository; import org.jboss.forge.furnace.services.ServiceRegistry; import org.jboss.forge.furnace.util.Assert; -import org.jboss.forge.furnace.util.CompletedFuture; -import org.jboss.forge.furnace.util.Sets; -import org.jboss.modules.Module; +import org.jboss.forge.furnace.util.NullFuture; /** * @author Lincoln Baxter, III */ public class AddonImpl implements Addon { - private static class Memento - { - public Set dependencies = Sets.getConcurrentSet(); - public Set missingDependencies = Sets.getConcurrentSet(); - - public AddonModuleLoader moduleLoader; - public Module module; - public AddonRunnable runnable; - public Future future = new CompletedFuture(null); - public AddonRepository repository; - public ServiceRegistry registry; - } - - public Set views = Sets.getConcurrentSet(); - @SuppressWarnings("unused") - private final LockManager lock; private final AddonId id; - private Memento state = new Memento(); + private AddonStateManager manager; - public AddonImpl(LockManager lock, AddonId id) + public AddonImpl(AddonStateManager manager, AddonId id) { - Assert.notNull(lock, "LockManager must not be null."); + Assert.notNull(manager, "Manager must not be null."); Assert.notNull(id, "AddonId must not be null."); this.id = id; - this.lock = lock; - } - - public boolean canBeStarted() - { - return getRunnable() == null && getStatus().isLoaded(); - } - - public boolean cancelFuture() - { - boolean result = false; - Future future = getFuture(); - if (future != null && !future.isDone()) - result = future.cancel(true); - return result; - } - - public void reset() - { - if (getModuleLoader() != null) - getModuleLoader().releaseAddonModule(views, id); - this.state = new Memento(); - this.views.clear(); + this.manager = manager; } @Override @@ -83,79 +40,31 @@ public AddonId getId() @Override public Set getDependencies() { - return Collections.unmodifiableSet(state.dependencies); - } - - public void setDependencies(Set dependencies) - { - Assert.notNull(dependencies, "Dependencies must not be null."); - - this.state.dependencies = Sets.getConcurrentSet(); - this.state.dependencies.addAll(dependencies); + return manager.getDependenciesOf(this); } @Override public ClassLoader getClassLoader() { - if (state.module != null) - return state.module.getClassLoader(); - return null; - } - - public Module getModule() - { - return state.module; - } - - public Addon setModule(Module module) - { - this.state.module = module; - return this; - } - - public AddonModuleLoader getModuleLoader() - { - return state.moduleLoader; + return manager.getClassLoaderOf(this); } - public void setModuleLoader(AddonModuleLoader moduleLoader) + @Override + public Future getFuture() { - this.state.moduleLoader = moduleLoader; + return manager.getFutureOf(this); } @Override public AddonRepository getRepository() { - return state.repository; - } - - public void setRepository(AddonRepository repository) - { - this.state.repository = repository; + return manager.getRepositoryOf(this); } @Override public ServiceRegistry getServiceRegistry() { - return state.registry; - } - - public Addon setServiceRegistry(ServiceRegistry registry) - { - Assert.notNull(registry, "Registry must not be null."); - this.state.registry = registry; - return this; - } - - public Set getViews() - { - return this.views; - } - - public void setViews(Set views) - { - this.views.clear(); - this.views.addAll(views); + return manager.getServiceRegistryOf(this); } @Override @@ -163,12 +72,12 @@ public AddonStatus getStatus() { AddonStatus result = AddonStatus.MISSING; - if (getClassLoader() != null && getMissingDependencies().isEmpty()) + if (getClassLoader() != null) result = AddonStatus.LOADED; if (getFuture() != null) { - if (!(getFuture() instanceof CompletedFuture)) + if (!(getFuture() instanceof NullFuture)) { if (getFuture().isDone()) result = AddonStatus.STARTED; @@ -181,48 +90,12 @@ public AddonStatus getStatus() return result; } - public void setMissingDependencies(Set missingDependencies) - { - Assert.notNull(missingDependencies, "Missing dependencies must not be null."); - - this.state.missingDependencies = Sets.getConcurrentSet(); - this.state.missingDependencies.addAll(missingDependencies); - } - - public Set getMissingDependencies() - { - return Collections.unmodifiableSet(state.missingDependencies); - } - - @Override - public Future getFuture() - { - return state.future; - } - - public void setFuture(Future future) - { - Assert.notNull(future, "Future must not be null."); - this.state.future = future; - } - - public AddonRunnable getRunnable() - { - return state.runnable; - } - - public void setRunnable(AddonRunnable runnable) - { - Assert.notNull(runnable, "Runnable must not be null."); - this.state.runnable = runnable; - } - @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append(getId().toCoordinates() + " +" + getStatus()); - if (canBeStarted()) + if (getFuture() == null) builder.append(" READY"); builder.append(" HC: ").append(hashCode()); return builder.toString(); @@ -234,7 +107,6 @@ public int hashCode() final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((views == null) ? 0 : views.hashCode()); return result; } @@ -255,13 +127,6 @@ public boolean equals(Object obj) } else if (!id.equals(other.id)) return false; - if (views == null) - { - if (other.views != null) - return false; - } - else if (!views.equals(other.views)) - return false; return true; } } diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/AddonLifecycleManager.java b/container/src/main/java/org/jboss/forge/furnace/addons/AddonLifecycleManager.java index 8ee9ec4d..f7e842cc 100644 --- a/container/src/main/java/org/jboss/forge/furnace/addons/AddonLifecycleManager.java +++ b/container/src/main/java/org/jboss/forge/furnace/addons/AddonLifecycleManager.java @@ -6,10 +6,9 @@ */ package org.jboss.forge.furnace.addons; -import java.util.Collections; +import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; @@ -20,6 +19,7 @@ import java.util.logging.Logger; import org.jboss.forge.furnace.FurnaceImpl; +import org.jboss.forge.furnace.exception.ContainerException; import org.jboss.forge.furnace.impl.graph.CompleteAddonGraph; import org.jboss.forge.furnace.impl.graph.MasterGraph; import org.jboss.forge.furnace.impl.graph.MasterGraphChangeHandler; @@ -30,6 +30,7 @@ import org.jboss.forge.furnace.util.AddonFilters; import org.jboss.forge.furnace.util.Assert; import org.jboss.forge.furnace.util.Callables; +import org.jboss.forge.furnace.util.ClassLoaders; import org.jboss.forge.furnace.util.Sets; /** @@ -39,16 +40,15 @@ public class AddonLifecycleManager { private static final Logger logger = Logger.getLogger(AddonLifecycleManager.class.getName()); - private final AtomicInteger starting = new AtomicInteger(-1); - private final ExecutorService executor = Executors.newCachedThreadPool(); - - private FurnaceImpl furnace; private final LockManager lock; - - private Set addons = Sets.getConcurrentSet(); + private FurnaceImpl furnace; private AddonLoader loader; + private AddonStateManager stateManager; - private MasterGraph currentGraph; + private Set addons = Sets.getConcurrentSet(); + private final Set views = Sets.getConcurrentSet(); + private final AtomicInteger starting = new AtomicInteger(-1); + private final ExecutorService executor = Executors.newCachedThreadPool(); public AddonLifecycleManager(FurnaceImpl furnace) { @@ -56,20 +56,19 @@ public AddonLifecycleManager(FurnaceImpl furnace) this.furnace = furnace; this.lock = furnace.getLockManager(); + this.stateManager = new AddonStateManager(lock); + this.loader = new AddonLoader(furnace, this, stateManager); logger.log(Level.FINE, "Instantiated AddonRTegistryImpl: " + this); } - private AddonLoader getAddonLoader() + public Addon getAddon(Set views, AddonId id) { - if (loader == null) - loader = new AddonLoader(furnace, this); - return loader; - } + Assert.notNull(views, "Addon view set must not be null."); + Assert.isTrue(!views.isEmpty(), "Addon view set must not be empty."); + Assert.notNull(id, "Addon ID must not be null."); - public void add(Addon addon) - { - addons.add(addon); + return getAddon(views.iterator().next(), id); } public Addon getAddon(final AddonView view, final AddonId id) @@ -91,6 +90,12 @@ public Addon call() throws Exception } } + if (result == null) + { + result = new AddonImpl(stateManager, id); + addons.add(result); + } + return result; } }); @@ -110,10 +115,10 @@ public Set call() throws Exception { HashSet result = new HashSet(); + AddonViewFilter viewFilter = new AddonViewFilter(stateManager, view); for (Addon addon : addons) { - Set views = ((AddonImpl) addon).getViews(); - if (views.contains(view) && filter.accept(addon)) + if (viewFilter.accept(addon) && filter.accept(addon)) result.add(addon); } @@ -122,24 +127,7 @@ public Set call() throws Exception }); } - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - - Iterator addonsIterator = addons.iterator(); - while (addonsIterator.hasNext()) - { - Addon addon = addonsIterator.next(); - builder.append("- ").append(addon.toString()); - if (addonsIterator.hasNext()) - builder.append("\n"); - } - - return builder.toString(); - } - - public void forceUpdate(final Set views) + public void forceUpdate() { lock.performLocked(LockMode.WRITE, new Callable() { @@ -164,17 +152,15 @@ public Void call() throws Exception System.out.println(master); } - MasterGraph last = currentGraph; - currentGraph = master; + MasterGraph last = stateManager.getCurrentGraph(); + stateManager.setCurrentGraph(master); for (Addon addon : addons) { - Callables.call(new StopAddonCallable(addon)); + Callables.call(new StopAddonCallable(stateManager, addon)); } - addons.clear(); - new MasterGraphChangeHandler(AddonLifecycleManager.this, last, master) - .hotSwapChanges(getAddonLoader()); + new MasterGraphChangeHandler(AddonLifecycleManager.this, stateManager, last, master).hotSwapChanges(); return null; } @@ -190,10 +176,7 @@ public Void call() throws Exception { for (Addon addon : addons) { - if (addon instanceof AddonImpl) - { - new StopAddonCallable(addon).call(); - } + new StopAddonCallable(stateManager, addon).call(); } List waiting = executor.shutdownNow(); @@ -205,28 +188,15 @@ public Void call() throws Exception }); } - private Set getAllEnabled(Set repositories) - { - Set result = new HashSet(); - for (AddonRepository repository : repositories) - { - for (AddonId enabled : repository.listEnabled()) - { - result.add(enabled); - } - } - return result; - } - - public void finishedStarting(AddonImpl addon) + public void finishedStarting(Addon addon) { starting.decrementAndGet(); } /** - * Returns true if there are currently any Addons being started. + * Returns true if there are currently any Addons being started. (Non-blocking.) */ - public boolean isStartingAddons(Set views) + public boolean isStartingAddons() { if (starting.get() == -1) return false; @@ -234,38 +204,94 @@ public boolean isStartingAddons(Set views) return starting.get() > 0; } - public Set getRepositories() + public void dispose(AddonView view) { - return Collections.unmodifiableSet(new LinkedHashSet(furnace.getRepositories())); + furnace.disposeAddonView(view); } - public AddonId resolve(AddonView view, final String name) + public void startAddon(Addon addon) { - Assert.notNull(name, "Addon name must not be null."); - AddonId result = null; - for (AddonId id : getAllEnabled(view.getRepositories())) + Assert.notNull(addon, "Addon to start must not be null."); + Callables.call(new StartEnabledAddonCallable(furnace, this, stateManager, executor, starting, addon)); + } + + public AddonView getRootView() + { + return furnace.getAddonRegistry(); + } + + public void addView(AddonView view) + { + this.views.add(view); + } + + public AddonRegistry findView(AddonRepository... repositories) + { + AddonRegistry result = null; + List furnaceRepositories = furnace.getRepositories(); + + for (AddonView view : views) { - if (name.equals(id.getName()) && (result == null || id.getVersion().compareTo(result.getVersion()) >= 0)) - result = id; - } + Set viewRepositories = view.getRepositories(); + if (repositories == null || repositories.length == 0) + { + if (viewRepositories.containsAll(furnaceRepositories) + && furnaceRepositories.containsAll(viewRepositories)) + result = (AddonRegistry) view; + } + else if (viewRepositories.containsAll(Arrays.asList(repositories)) + && Arrays.asList(repositories).containsAll(viewRepositories)) + { + result = (AddonRegistry) view; + } + if (result != null) + break; + } return result; } - public void dispose(AddonView view) + public void removeView(AddonView view) { - furnace.disposeAddonView(view); + if (!views.contains(view)) + throw new IllegalArgumentException("The given view does not belong to this Furnace instance."); } - public void startAddon(Addon addon) + @Override + public String toString() { - Assert.notNull(addon, "Addon to start must not be null."); - Callables.call(new StartEnabledAddonCallable(furnace, executor, starting, (AddonImpl) addon)); + StringBuilder builder = new StringBuilder(); + + Iterator addonsIterator = addons.iterator(); + while (addonsIterator.hasNext()) + { + Addon addon = addonsIterator.next(); + builder.append("- ").append(addon.toString()); + if (addonsIterator.hasNext()) + builder.append("\n"); + } + + return builder.toString(); } - public AddonView getRootView() + public void loadAddon(final Addon addon) { - return furnace.getAddonRegistry(); + try + { + ClassLoaders.executeIn(this.getClass().getClassLoader(), new Callable() + { + @Override + public Void call() throws Exception + { + loader.loadAddon(addon); + return null; + } + }); + } + catch (Exception e) + { + throw new ContainerException("Could not load addon: " + addon.getId(), e); + } } } diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/AddonLoader.java b/container/src/main/java/org/jboss/forge/furnace/addons/AddonLoader.java index b7fb59b4..b3f6b17e 100644 --- a/container/src/main/java/org/jboss/forge/furnace/addons/AddonLoader.java +++ b/container/src/main/java/org/jboss/forge/furnace/addons/AddonLoader.java @@ -6,6 +6,7 @@ import java.util.logging.Logger; import org.jboss.forge.furnace.Furnace; +import org.jboss.forge.furnace.exception.ContainerException; import org.jboss.forge.furnace.lock.LockManager; import org.jboss.forge.furnace.modules.AddonModuleLoader; import org.jboss.forge.furnace.repositories.AddonDependencyEntry; @@ -18,121 +19,82 @@ public class AddonLoader private static final Logger logger = Logger.getLogger(AddonLoader.class.getName()); private LockManager lock; - private AddonLifecycleManager manager; - + private AddonLifecycleManager lifecycleManager; + private AddonStateManager stateManager; private AddonModuleLoader loader; - public AddonLoader(Furnace furnace, AddonLifecycleManager manager) + public AddonLoader(Furnace furnace, AddonLifecycleManager lifecycleManager, AddonStateManager stateManager) { this.lock = furnace.getLockManager(); - this.manager = manager; - this.loader = new AddonModuleLoader(furnace, manager); + this.lifecycleManager = lifecycleManager; + this.stateManager = stateManager; + this.loader = new AddonModuleLoader(furnace, lifecycleManager, stateManager); } - public AddonImpl loadAddon(Set views, AddonId addonId) + public void loadAddon(Addon addon) { - Assert.notNull(addonId, "AddonId to load must not be null."); - - AddonImpl addon = null; - - AddonView view = views.iterator().next(); - for (Addon existing : view.getAddons()) - { - if (existing.getId().equals(addonId)) - { - addon = (AddonImpl) existing; - break; - } - } - - if (addon == null || addon.getStatus().isMissing()) - { - for (AddonRepository repository : view.getRepositories()) - { - addon = loadAddonFromRepository(views, view, repository, addonId); - if (addon != null) - break; - } - } + Assert.notNull(addon, "Addon to load must not be null."); - if (addon != null) - manager.add(addon); - - return addon; - } - - private AddonImpl loadAddonFromRepository(Set views, AddonView view, AddonRepository repository, - final AddonId addonId) - { - AddonImpl addon = null; - if (repository.isEnabled(addonId) && repository.isDeployed(addonId)) + if (addon.getStatus().isMissing()) { - addon = (AddonImpl) view.getAddon(addonId); - - if (addon == null) + AddonRepository repository = + stateManager.getViewsOf(addon).iterator().next().getRepositories().iterator().next(); + if (repository.isEnabled(addon.getId()) + && repository.isDeployed(addon.getId())) { - addon = new AddonImpl(lock, addonId); - addon.setRepository(repository); - } + Set dependencies = fromAddonDependencyEntries(addon, + repository.getAddonDependencies(addon.getId())); - Set dependencies = fromAddonDependencyEntries(views, view, addon, - repository.getAddonDependencies(addonId)); - - if (addon.getModule() == null) - { Set missingRequiredDependencies = new HashSet(); for (AddonDependency addonDependency : dependencies) { - Addon dependency = addonDependency.getDependency(); - if (dependency == null && !addonDependency.isOptional()) + if (addonDependency instanceof MissingAddonDependencyImpl && !addonDependency.isOptional()) { missingRequiredDependencies.add(addonDependency); } } - if (missingRequiredDependencies.isEmpty()) - addon.setMissingDependencies(missingRequiredDependencies); - if (!missingRequiredDependencies.isEmpty()) { - if (addon.getMissingDependencies().size() != missingRequiredDependencies.size()) + if (stateManager.getMissingDependenciesOf(addon).size() != missingRequiredDependencies.size()) { logger.warning("Addon [" + addon + "] has [" + missingRequiredDependencies.size() + "] missing dependencies: " + missingRequiredDependencies + " and will be not be loaded until all required" + " dependencies are available."); } - addon.setMissingDependencies(missingRequiredDependencies); + stateManager.setState(addon, new AddonState(missingRequiredDependencies)); } else { try { - Module module = loader.loadModule(views, view, addonId); - addon.setModuleLoader(loader); - addon.setModule(module); - addon.setRepository(repository); + Module module = loader.loadAddonModule(addon); + stateManager.setState(addon, new AddonState(dependencies, repository, loader, module)); + } + catch (RuntimeException e) + { + logger.log(Level.FINE, "Failed to load addon [" + addon.getId() + "]", e); + throw e; } catch (Exception e) { - logger.log(Level.FINE, "Failed to load addon [" + addonId + "]", e); + logger.log(Level.FINE, "Failed to load addon [" + addon.getId() + "]", e); + throw new ContainerException("Failed to load addon [" + addon.getId() + "]", e); } } } - - dependencies.removeAll(addon.getMissingDependencies()); - addon.setDependencies(dependencies); } - return addon; } - private Set fromAddonDependencyEntries(Set views, AddonView view, AddonImpl addon, + private Set fromAddonDependencyEntries(Addon addon, Set entries) { Set result = new HashSet(); for (AddonDependencyEntry entry : entries) { - AddonId dependencyId = manager.resolve(view, entry.getName()); + Set views = stateManager.getViewsOf(addon); + AddonId dependencyId = stateManager.resolveAddonId(views, entry.getName()); if (dependencyId == null) { if (!entry.isOptional()) @@ -142,10 +104,8 @@ private Set fromAddonDependencyEntries(Set views, Ad } else { - AddonImpl dependency = loadAddon(views, dependencyId); + Addon dependency = lifecycleManager.getAddon(views.iterator().next(), dependencyId); result.add(new AddonDependencyImpl(lock, - addon, - dependency.getId().getVersion(), dependency, entry.isExported(), entry.isOptional())); diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/AddonRunnable.java b/container/src/main/java/org/jboss/forge/furnace/addons/AddonRunnable.java index f4e6e0ef..87650f39 100644 --- a/container/src/main/java/org/jboss/forge/furnace/addons/AddonRunnable.java +++ b/container/src/main/java/org/jboss/forge/furnace/addons/AddonRunnable.java @@ -13,20 +13,16 @@ import javax.enterprise.inject.spi.BeanManager; import org.jboss.forge.furnace.Furnace; -import org.jboss.forge.furnace.FurnaceImpl; -import org.jboss.forge.furnace.addons.Addon; -import org.jboss.forge.furnace.addons.AddonDependency; import org.jboss.forge.furnace.event.PostStartup; import org.jboss.forge.furnace.event.PreShutdown; +import org.jboss.forge.furnace.exception.ContainerException; import org.jboss.forge.furnace.impl.AddonProducer; import org.jboss.forge.furnace.impl.AddonRegistryProducer; import org.jboss.forge.furnace.impl.AddonRepositoryProducer; import org.jboss.forge.furnace.impl.ContainerServiceExtension; import org.jboss.forge.furnace.impl.FurnaceProducer; -import org.jboss.forge.furnace.impl.NullServiceRegistry; import org.jboss.forge.furnace.impl.ServiceRegistryImpl; import org.jboss.forge.furnace.impl.ServiceRegistryProducer; -import org.jboss.forge.furnace.lock.LockMode; import org.jboss.forge.furnace.modules.AddonResourceLoader; import org.jboss.forge.furnace.modules.ModularURLScanner; import org.jboss.forge.furnace.modules.ModularWeld; @@ -48,7 +44,7 @@ public final class AddonRunnable implements Runnable private static final Logger logger = Logger.getLogger(AddonRunnable.class.getName()); private Furnace furnace; - private AddonImpl addon; + private Addon addon; private AddonContainerStartup container; private Callable shutdownCallable = new Callable() @@ -60,9 +56,17 @@ public Object call() throws Exception } }; - public AddonRunnable(Furnace forge, AddonImpl addon) + private AddonLifecycleManager lifecycleManager; + private AddonStateManager stateManager; + + public AddonRunnable(Furnace furnace, + AddonLifecycleManager lifecycleManager, + AddonStateManager stateManager, + Addon addon) { - this.furnace = forge; + this.lifecycleManager = lifecycleManager; + this.stateManager = stateManager; + this.furnace = furnace; this.addon = addon; } @@ -70,26 +74,23 @@ public void shutdown() { try { - furnace.getLockManager().performLocked(LockMode.READ, new Callable() - { - @Override - public Void call() throws Exception - { - logger.info("< Stopping container [" + addon.getId() + "] [" + addon.getRepository().getRootDirectory() - + "]"); - long start = System.currentTimeMillis(); - ClassLoaders.executeIn(addon.getClassLoader(), shutdownCallable); - logger.info("<< Stopped container [" + addon.getId() + "] - " - + (System.currentTimeMillis() - start) + "ms"); - return null; - } - }); + logger.info("< Stopping container [" + addon.getId() + "] [" + addon.getRepository().getRootDirectory() + + "]"); + long start = System.currentTimeMillis(); + ClassLoaders.executeIn(addon.getClassLoader(), shutdownCallable); + logger.info("<< Stopped container [" + addon.getId() + "] - " + + (System.currentTimeMillis() - start) + "ms"); } catch (RuntimeException e) { logger.log(Level.SEVERE, "Failed to shut down addon " + addon.getId(), e); throw e; } + catch (Exception e) + { + logger.log(Level.SEVERE, "Failed to shut down addon " + addon.getId(), e); + throw new ContainerException("Failed to shut down addon " + addon.getId(), e); + } } @Override @@ -100,39 +101,32 @@ public void run() currentThread.setName(addon.getId().toCoordinates()); try { - furnace.getLockManager().performLocked(LockMode.READ, new Callable() - { - @Override - public Void call() throws Exception - { - logger.info("> Starting container [" + addon.getId() + "] [" + addon.getRepository().getRootDirectory() - + "]"); - long start = System.currentTimeMillis(); - container = new AddonContainerStartup(); - shutdownCallable = ClassLoaders.executeIn(addon.getClassLoader(), container); - logger.info(">> Started container [" + addon.getId() + "] - " - + (System.currentTimeMillis() - start) + "ms"); - return null; - } - }); + logger.info("> Starting container [" + addon.getId() + "] [" + addon.getRepository().getRootDirectory() + + "]"); + long start = System.currentTimeMillis(); + container = new AddonContainerStartup(); + shutdownCallable = ClassLoaders.executeIn(addon.getClassLoader(), container); + logger.info(">> Started container [" + addon.getId() + "] - " + + (System.currentTimeMillis() - start) + "ms"); if (container.postStartupTask != null) ClassLoaders.executeIn(addon.getClassLoader(), container.postStartupTask); } catch (Throwable e) { - logger.log(Level.SEVERE, "Failed to start addon [" + addon.getId() + "] with module [" + addon.getModule() + logger.log(Level.SEVERE, "Failed to start addon [" + addon.getId() + "] with classloader [" + + stateManager.getClassLoaderOf(addon) + "]", e); throw new RuntimeException(e); } finally { - ((FurnaceImpl) furnace).getAddonLifecycleManager().finishedStarting(addon); + lifecycleManager.finishedStarting(addon); currentThread.setName(name); } } - public AddonImpl getAddon() + public Addon getAddon() { return addon; } @@ -157,8 +151,6 @@ public Callable call() throws Exception /* * This is an import-only addon and does not require weld, nor provide remote services. */ - addon.setServiceRegistry(new NullServiceRegistry()); - shutdownCallback = new Callable() { @Override @@ -200,7 +192,7 @@ public Object call() throws Exception ServiceRegistry registry = BeanManagerUtils.getContextualInstance(manager, ServiceRegistry.class); Assert.notNull(registry, "Service registry was null."); - addon.setServiceRegistry(registry); + stateManager.setServiceRegistry(addon, registry); logger.info("Services loaded from addon [" + addon.getId() + "] - " + registry.getExportedTypes()); diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/AddonState.java b/container/src/main/java/org/jboss/forge/furnace/addons/AddonState.java new file mode 100644 index 00000000..eebc1241 --- /dev/null +++ b/container/src/main/java/org/jboss/forge/furnace/addons/AddonState.java @@ -0,0 +1,110 @@ +package org.jboss.forge.furnace.addons; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Future; + +import org.jboss.forge.furnace.impl.NullServiceRegistry; +import org.jboss.forge.furnace.modules.AddonModuleLoader; +import org.jboss.forge.furnace.repositories.AddonRepository; +import org.jboss.forge.furnace.services.ServiceRegistry; +import org.jboss.forge.furnace.util.Assert; +import org.jboss.forge.furnace.util.NullFuture; +import org.jboss.modules.Module; + +public class AddonState +{ + private Future future = new NullFuture(null); + private Set dependencies = new HashSet(); + private Set missingDependencies = new HashSet(); + private AddonRepository repository; + private ServiceRegistry registry = new NullServiceRegistry(); + private AddonModuleLoader loader; + private Module module; + private AddonRunnable runnable; + + public AddonState(Set dependencies, AddonRepository repository, AddonModuleLoader loader, + Module module) + { + Assert.notNull(dependencies, "Addon dependency set must not be null."); + Assert.notNull(repository, "Addon repository must not be null."); + Assert.notNull(loader, "Addon loader must not be null."); + Assert.notNull(module, "Addon Module must not be null."); + + this.dependencies = dependencies; + this.repository = repository; + this.loader = loader; + this.module = module; + } + + public AddonState(Set missingDependencies) + { + Assert.notNull(missingDependencies, "Missing dependency set must not be null."); + this.missingDependencies = missingDependencies; + } + + public AddonState() + { + } + + public ClassLoader getClassLoader() + { + return module != null ? module.getClassLoader() : null; + } + + public Module getModule() + { + return module; + } + + public Set getDependencies() + { + return dependencies; + } + + public Set getMissingDependencies() + { + return missingDependencies; + } + + public Future getFuture() + { + return future; + } + + public void setFuture(Future future) + { + this.future = future; + } + + public AddonRepository getRepository() + { + return repository; + } + + public AddonRunnable getRunnable() + { + return runnable; + } + + public void setRunnable(AddonRunnable runnable) + { + this.runnable = runnable; + } + + public ServiceRegistry getServiceRegistry() + { + return registry; + } + + public void setServiceRegistry(ServiceRegistry registry) + { + this.registry = registry; + } + + public AddonModuleLoader getModuleLoader() + { + return loader; + } + +} diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/AddonStateManager.java b/container/src/main/java/org/jboss/forge/furnace/addons/AddonStateManager.java new file mode 100644 index 00000000..9b9b00c9 --- /dev/null +++ b/container/src/main/java/org/jboss/forge/furnace/addons/AddonStateManager.java @@ -0,0 +1,225 @@ +package org.jboss.forge.furnace.addons; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; + +import org.jboss.forge.furnace.impl.graph.AddonVertex; +import org.jboss.forge.furnace.impl.graph.MasterGraph; +import org.jboss.forge.furnace.lock.LockManager; +import org.jboss.forge.furnace.lock.LockMode; +import org.jboss.forge.furnace.modules.AddonModuleLoader; +import org.jboss.forge.furnace.repositories.AddonRepository; +import org.jboss.forge.furnace.services.ServiceRegistry; +import org.jboss.forge.furnace.util.Assert; + +public class AddonStateManager +{ + private LockManager lock; + private MasterGraph graph; + private Map states = new HashMap(); + + public AddonStateManager(LockManager lock) + { + this.lock = lock; + } + + public void reset(final Addon addon) + { + lock.performLocked(LockMode.WRITE, new Callable() + { + @Override + public Void call() throws Exception + { + states.remove(addon); + return null; + } + }); + } + + public Set getDependenciesOf(Addon addon) + { + return getState(addon).getDependencies(); + } + + public Set getMissingDependenciesOf(Addon addon) + { + return getState(addon).getMissingDependencies(); + } + + public ClassLoader getClassLoaderOf(Addon addon) + { + return getState(addon).getClassLoader(); + } + + public Future getFutureOf(Addon addon) + { + return getState(addon).getFuture(); + } + + public AddonRepository getRepositoryOf(Addon addon) + { + return getState(addon).getRepository(); + } + + public AddonRunnable getRunnableOf(Addon addon) + { + return getState(addon).getRunnable(); + } + + public ServiceRegistry getServiceRegistryOf(Addon addon) + { + return getState(addon).getServiceRegistry(); + } + + public Set getViewsOf(Addon addon) + { + Set result = new HashSet(); + AddonVertex vertex = graph.getVertex(addon.getId().getName(), addon.getId().getVersion()); + if (vertex != null) + result.addAll(vertex.getViews()); + return result; + } + + private AddonState getState(final Addon addon) + { + return lock.performLocked(LockMode.READ, new Callable() + { + @Override + public AddonState call() throws Exception + { + AddonState result = states.get(addon); + if (result == null) + result = new AddonState(); + return result; + } + }); + } + + public void setState(final Addon addon, final AddonState state) + { + lock.performLocked(LockMode.WRITE, new Callable() + { + @Override + public Void call() throws Exception + { + states.put(addon, state); + return null; + } + }); + } + + public MasterGraph getCurrentGraph() + { + return graph; + } + + public void setCurrentGraph(final MasterGraph graph) + { + lock.performLocked(LockMode.WRITE, new Callable() + { + @Override + public Void call() throws Exception + { + AddonStateManager.this.setGraph(graph); + return null; + } + }); + } + + private void setGraph(MasterGraph graph) + { + this.graph = graph; + } + + public AddonId resolveAddonId(Set views, String name) + { + Assert.notNull(views, "Views must not be null."); + Assert.isTrue(!views.isEmpty(), "Views must not be empty."); + Assert.notNull(name, "Addon name must not be null."); + + AddonId result = null; + + AddonView view = views.iterator().next(); + for (AddonId id : getAllEnabled(view.getRepositories())) + { + if (name.equals(id.getName()) && (result == null || id.getVersion().compareTo(result.getVersion()) >= 0)) + result = id; + } + + return result; + } + + private Set getAllEnabled(Set repositories) + { + Set result = new HashSet(); + for (AddonRepository repository : repositories) + { + for (AddonId enabled : repository.listEnabled()) + { + result.add(enabled); + } + } + return result; + } + + public boolean cancel(Addon addon) + { + boolean result = false; + + AddonState state = getState(addon); + + Future future = getFutureOf(addon); + if (future != null && !future.isDone()) + result = future.cancel(true); + + AddonModuleLoader loader = state.getModuleLoader(); + if (loader != null) + loader.releaseAddonModule(addon); + + setState(addon, null); + + return result; + } + + public boolean canBeLoaded(Addon addon) + { + return getMissingDependenciesOf(addon).isEmpty(); + } + + public boolean canBeStarted(Addon addon) + { + return getRunnableOf(addon) == null + && addon.getStatus().isLoaded(); + } + + public void setHandles(final Addon addon, final Future result, final AddonRunnable runnable) + { + lock.performLocked(LockMode.WRITE, new Callable() + { + @Override + public Void call() throws Exception + { + getState(addon).setFuture(result); + getState(addon).setRunnable(runnable); + return null; + } + }); + } + + public void setServiceRegistry(final Addon addon, final ServiceRegistry registry) + { + lock.performLocked(LockMode.WRITE, new Callable() + { + @Override + public Void call() throws Exception + { + getState(addon).setServiceRegistry(registry); + return null; + } + }); + } +} diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/AddonViewFilter.java b/container/src/main/java/org/jboss/forge/furnace/addons/AddonViewFilter.java new file mode 100644 index 00000000..6a5a8080 --- /dev/null +++ b/container/src/main/java/org/jboss/forge/furnace/addons/AddonViewFilter.java @@ -0,0 +1,28 @@ +package org.jboss.forge.furnace.addons; + +/** + * An {@link AddonFilter} that filters on the {@link AddonView} containers of the given {@link Addon}. + * + * @author Lincoln Baxter, III + */ +public final class AddonViewFilter implements AddonFilter +{ + private AddonStateManager manager; + private AddonView view; + + public AddonViewFilter(AddonStateManager manager, AddonView view) + { + this.manager = manager; + this.view = view; + } + + @Override + public boolean accept(Addon addon) + { + if (manager.getViewsOf(addon).contains(view)) + { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/MissingAddonDependencyImpl.java b/container/src/main/java/org/jboss/forge/furnace/addons/MissingAddonDependencyImpl.java index 06466231..bb09ed9f 100644 --- a/container/src/main/java/org/jboss/forge/furnace/addons/MissingAddonDependencyImpl.java +++ b/container/src/main/java/org/jboss/forge/furnace/addons/MissingAddonDependencyImpl.java @@ -1,9 +1,6 @@ package org.jboss.forge.furnace.addons; -import org.jboss.forge.furnace.addons.Addon; -import org.jboss.forge.furnace.addons.AddonDependency; import org.jboss.forge.furnace.repositories.AddonDependencyEntry; -import org.jboss.forge.furnace.versions.Version; public class MissingAddonDependencyImpl implements AddonDependency { @@ -15,24 +12,12 @@ public MissingAddonDependencyImpl(AddonDependencyEntry entry) this.entry = entry; } - @Override - public Addon getDependent() - { - return null; - } - @Override public Addon getDependency() { return null; } - @Override - public Version getDependencyVersion() - { - return null; - } - @Override public boolean isExported() { @@ -53,7 +38,7 @@ public String getMissingAddonName() @Override public String toString() { - return "MissingAddonDependencyImpl [entry=" + entry + "]"; + return "Missing: " + entry + ""; } } diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/StartEnabledAddonCallable.java b/container/src/main/java/org/jboss/forge/furnace/addons/StartEnabledAddonCallable.java index 2b77e080..052d64e2 100644 --- a/container/src/main/java/org/jboss/forge/furnace/addons/StartEnabledAddonCallable.java +++ b/container/src/main/java/org/jboss/forge/furnace/addons/StartEnabledAddonCallable.java @@ -12,15 +12,23 @@ */ public class StartEnabledAddonCallable implements Callable { + private Furnace furnace; + private AddonLifecycleManager lifecycleManager; + private AddonStateManager stateManager; private ExecutorService executor; private AtomicInteger starting; - private AddonImpl addon; - private Furnace furnace; + private Addon addon; - public StartEnabledAddonCallable(Furnace furnace, ExecutorService executor, AtomicInteger starting, - AddonImpl toStart) + public StartEnabledAddonCallable(Furnace furnace, + AddonLifecycleManager lifecycleManager, + AddonStateManager stateManager, + ExecutorService executor, + AtomicInteger starting, + Addon toStart) { this.furnace = furnace; + this.lifecycleManager = lifecycleManager; + this.stateManager = stateManager; this.executor = executor; this.starting = starting; this.addon = toStart; @@ -29,7 +37,7 @@ public StartEnabledAddonCallable(Furnace furnace, ExecutorService executor, Atom @Override public Void call() { - if (addon.canBeStarted()) + if (stateManager.canBeStarted(addon)) { if (executor.isShutdown()) { @@ -37,13 +45,12 @@ public Void call() } Future result = null; - if (addon.getRunnable() == null) + if (stateManager.getRunnableOf(addon) == null) { starting.incrementAndGet(); - AddonRunnable runnable = new AddonRunnable(furnace, addon); + AddonRunnable runnable = new AddonRunnable(furnace, lifecycleManager, stateManager, addon); result = executor.submit(runnable, null); - addon.setFuture(result); - addon.setRunnable(runnable); + stateManager.setHandles(addon, result, runnable); } } return null; diff --git a/container/src/main/java/org/jboss/forge/furnace/addons/StopAddonCallable.java b/container/src/main/java/org/jboss/forge/furnace/addons/StopAddonCallable.java index ce73a4ca..bd93f7b3 100644 --- a/container/src/main/java/org/jboss/forge/furnace/addons/StopAddonCallable.java +++ b/container/src/main/java/org/jboss/forge/furnace/addons/StopAddonCallable.java @@ -11,6 +11,7 @@ import java.util.logging.Logger; import org.jboss.forge.furnace.addons.Addon; +import org.jboss.forge.furnace.util.Assert; /** * @author Lincoln Baxter, III @@ -20,38 +21,37 @@ public class StopAddonCallable implements Callable { private static final Logger logger = Logger.getLogger(StopAddonCallable.class.getName()); - private AddonImpl addon; + private AddonStateManager stateManager; + private Addon addon; - public StopAddonCallable(Addon addon) + public StopAddonCallable(AddonStateManager stateManager, Addon addon) { - super(); - if (addon instanceof AddonImpl) - this.addon = (AddonImpl) addon; + Assert.notNull(stateManager, "State manager must not be null."); + Assert.notNull(addon, "Addon to stop must not be null."); + + this.stateManager = stateManager; + this.addon = addon; } @Override public Void call() throws Exception { - if (addon != null) + AddonRunnable runnable = stateManager.getRunnableOf(addon); + try { - AddonRunnable runnable = ((AddonImpl) addon).getRunnable(); - try - { - if (runnable != null) - { - runnable.shutdown(); - } - } - catch (Exception e) - { - logger.log(Level.WARNING, "Failed to shut down addon " + addon, e); - } - finally + if (runnable != null) { - addon.cancelFuture(); - addon.reset(); + runnable.shutdown(); } } + catch (Exception e) + { + logger.log(Level.WARNING, "Failed to shut down addon " + addon, e); + } + finally + { + stateManager.cancel(addon); + } return null; } diff --git a/container/src/main/java/org/jboss/forge/furnace/impl/AddonRegistryImpl.java b/container/src/main/java/org/jboss/forge/furnace/impl/AddonRegistryImpl.java index 9854b4a1..3b8f2f2d 100644 --- a/container/src/main/java/org/jboss/forge/furnace/impl/AddonRegistryImpl.java +++ b/container/src/main/java/org/jboss/forge/furnace/impl/AddonRegistryImpl.java @@ -105,7 +105,7 @@ public Set call() throws Exception { HashSet result = new HashSet(); - for (Addon addon : manager.getAddons(AddonRegistryImpl.this, new AddonRepositoryFilter(getRepositories()))) + for (Addon addon : manager.getAddons(AddonRegistryImpl.this)) { if (filter.accept(addon)) result.add(addon); diff --git a/container/src/main/java/org/jboss/forge/furnace/impl/AddonRepositoryFilter.java b/container/src/main/java/org/jboss/forge/furnace/impl/AddonRepositoryFilter.java deleted file mode 100644 index c3c51688..00000000 --- a/container/src/main/java/org/jboss/forge/furnace/impl/AddonRepositoryFilter.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.jboss.forge.furnace.impl; - -import java.util.Collection; - -import org.jboss.forge.furnace.addons.Addon; -import org.jboss.forge.furnace.addons.AddonFilter; -import org.jboss.forge.furnace.repositories.AddonRepository; - -/** - * An {@link AddonFilter} that filters on the origin repository of the given addon. - * - * @author Lincoln Baxter, III - */ -public final class AddonRepositoryFilter implements AddonFilter -{ - private Collection repositories; - - public AddonRepositoryFilter(Collection repositories) - { - this.repositories = repositories; - } - - @Override - public boolean accept(Addon addon) - { - for (AddonRepository repository : repositories) - { - if (repository.equals(addon.getRepository())) - { - return true; - } - } - return false; - } -} \ No newline at end of file diff --git a/container/src/main/java/org/jboss/forge/furnace/impl/ServiceRegistryImpl.java b/container/src/main/java/org/jboss/forge/furnace/impl/ServiceRegistryImpl.java index bc7e5d1e..ddd74b51 100644 --- a/container/src/main/java/org/jboss/forge/furnace/impl/ServiceRegistryImpl.java +++ b/container/src/main/java/org/jboss/forge/furnace/impl/ServiceRegistryImpl.java @@ -11,7 +11,6 @@ import javax.enterprise.inject.spi.BeanManager; import org.jboss.forge.furnace.addons.Addon; -import org.jboss.forge.furnace.addons.AddonImpl; import org.jboss.forge.furnace.lock.LockManager; import org.jboss.forge.furnace.lock.LockMode; import org.jboss.forge.furnace.services.ExportedInstance; @@ -28,13 +27,13 @@ public class ServiceRegistryImpl implements ServiceRegistry private BeanManager manager; - private AddonImpl addon; + private Addon addon; private Logger log = Logger.getLogger(getClass().getName()); private LockManager lock; - public ServiceRegistryImpl(LockManager lock, AddonImpl addon, BeanManager manager, + public ServiceRegistryImpl(LockManager lock, Addon addon, BeanManager manager, ContainerServiceExtension extension) { this.lock = lock; diff --git a/container/src/main/java/org/jboss/forge/furnace/impl/graph/AddonVertex.java b/container/src/main/java/org/jboss/forge/furnace/impl/graph/AddonVertex.java index 031b4157..2d32924c 100644 --- a/container/src/main/java/org/jboss/forge/furnace/impl/graph/AddonVertex.java +++ b/container/src/main/java/org/jboss/forge/furnace/impl/graph/AddonVertex.java @@ -3,6 +3,7 @@ import java.util.HashSet; import java.util.Set; +import org.jboss.forge.furnace.addons.Addon; import org.jboss.forge.furnace.addons.AddonId; import org.jboss.forge.furnace.addons.AddonView; import org.jboss.forge.furnace.util.Assert; @@ -13,6 +14,7 @@ public class AddonVertex private String name; private Version version; private Set views = new HashSet(); + private Addon addon; public AddonVertex(String name, Version version) { @@ -22,6 +24,16 @@ public AddonVertex(String name, Version version) this.version = version; } + public Addon getAddon() + { + return addon; + } + + public void setAddon(Addon addon) + { + this.addon = addon; + } + public String getName() { return name; diff --git a/container/src/main/java/org/jboss/forge/furnace/impl/graph/MasterGraph.java b/container/src/main/java/org/jboss/forge/furnace/impl/graph/MasterGraph.java index 2c5e085d..d51e5b14 100644 --- a/container/src/main/java/org/jboss/forge/furnace/impl/graph/MasterGraph.java +++ b/container/src/main/java/org/jboss/forge/furnace/impl/graph/MasterGraph.java @@ -2,6 +2,7 @@ import java.util.Set; +import org.jboss.forge.furnace.versions.Version; import org.jgrapht.DirectedGraph; import org.jgrapht.Graphs; import org.jgrapht.event.TraversalListenerAdapter; @@ -22,6 +23,9 @@ public DirectedGraph getGraph() public void merge(final OptimizedAddonGraph other) { + if (other.getGraph().vertexSet().isEmpty()) + return; + if (graph.vertexSet().isEmpty()) { if (!Graphs.addGraph(graph, other.getGraph())) @@ -117,4 +121,10 @@ protected void enhanceNewVertex(AddonVertex vertex) // Intentionally blank. } + @Override + public AddonVertex getVertex(String name, Version version) + { + return super.getVertex(name, version); + } + } diff --git a/container/src/main/java/org/jboss/forge/furnace/impl/graph/MasterGraphChangeHandler.java b/container/src/main/java/org/jboss/forge/furnace/impl/graph/MasterGraphChangeHandler.java index b94e2dc6..fbe3e7d8 100644 --- a/container/src/main/java/org/jboss/forge/furnace/impl/graph/MasterGraphChangeHandler.java +++ b/container/src/main/java/org/jboss/forge/furnace/impl/graph/MasterGraphChangeHandler.java @@ -1,58 +1,56 @@ package org.jboss.forge.furnace.impl.graph; -import org.jboss.forge.furnace.addons.AddonImpl; +import org.jboss.forge.furnace.addons.Addon; +import org.jboss.forge.furnace.addons.AddonId; import org.jboss.forge.furnace.addons.AddonLifecycleManager; -import org.jboss.forge.furnace.addons.AddonLoader; +import org.jboss.forge.furnace.addons.AddonStateManager; +import org.jboss.forge.furnace.addons.AddonView; import org.jgrapht.event.TraversalListenerAdapter; import org.jgrapht.event.VertexTraversalEvent; import org.jgrapht.traverse.DepthFirstIterator; public class MasterGraphChangeHandler { - private AddonLifecycleManager manager; + private AddonStateManager stateManager; + private AddonLifecycleManager lifecycleManager; private MasterGraph currentGraph; private MasterGraph graph; - public MasterGraphChangeHandler(AddonLifecycleManager manager, MasterGraph currentGraph, MasterGraph graph) + public MasterGraphChangeHandler(AddonLifecycleManager lifefycleManager, AddonStateManager stateManager, + MasterGraph currentGraph, MasterGraph graph) { - this.manager = manager; + this.lifecycleManager = lifefycleManager; + this.stateManager = stateManager; this.currentGraph = currentGraph; this.graph = graph; } - public void hotSwapChanges(AddonLoader loader) + public void hotSwapChanges() { - startupIncremental(manager, loader); + initGraph(); + startupIncremental(); } - private void startupIncremental(final AddonLifecycleManager manager, final AddonLoader loader) + private void initGraph() { DepthFirstIterator iterator = new DepthFirstIterator( graph.getGraph()); iterator.addTraversalListener(new TraversalListenerAdapter() { + @Override public void vertexTraversed(VertexTraversalEvent event) { AddonVertex vertex = event.getVertex(); - AddonImpl addon = null; - if (addon == null) - { - addon = loader.loadAddon(vertex.getViews(), vertex.getAddonId()); - - if (addon != null && !addon.getStatus().isMissing()) - { - addon.setViews(vertex.getViews()); - System.out.println("Queueing [" + addon + "] for startup."); - manager.startAddon(addon); - } - else - { - System.out.println("Null/missing addon detected."); - } - } + AddonView view = vertex.getViews().iterator().next(); + AddonId addonId = vertex.getAddonId(); + Addon addon = lifecycleManager.getAddon(view, addonId); + + if (stateManager.canBeLoaded(addon)) + lifecycleManager.loadAddon(addon); + vertex.setAddon(addon); }; }); @@ -60,4 +58,23 @@ public void vertexTraversed(VertexTraversalEvent event) iterator.next(); } + private void startupIncremental() + { + DepthFirstIterator iterator = new DepthFirstIterator( + graph.getGraph()); + + iterator.addTraversalListener(new TraversalListenerAdapter() + { + @Override + public void vertexTraversed(VertexTraversalEvent event) + { + AddonVertex vertex = event.getVertex(); + Addon addon = vertex.getAddon(); + lifecycleManager.startAddon(addon); + }; + }); + + while (iterator.hasNext()) + iterator.next(); + } } diff --git a/container/src/main/java/org/jboss/forge/furnace/modules/AddonModuleIdentifierCache.java b/container/src/main/java/org/jboss/forge/furnace/modules/AddonModuleIdentifierCache.java index 9a0e74aa..22c18b34 100644 --- a/container/src/main/java/org/jboss/forge/furnace/modules/AddonModuleIdentifierCache.java +++ b/container/src/main/java/org/jboss/forge/furnace/modules/AddonModuleIdentifierCache.java @@ -10,11 +10,10 @@ import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import java.util.UUID; +import org.jboss.forge.furnace.addons.Addon; import org.jboss.forge.furnace.addons.AddonId; -import org.jboss.forge.furnace.addons.AddonView; import org.jboss.modules.ModuleIdentifier; /** @@ -23,19 +22,18 @@ */ class AddonModuleIdentifierCache { - private Map map = new HashMap(); + private Map map = new HashMap(); - public void clear(Set views, AddonId addonId) + public void clear(Addon addon) { - map.remove(addonId); + map.remove(addon); } - public ModuleIdentifier getModuleId(Set views, AddonId addonId) + public ModuleIdentifier getModuleId(Addon addon) { - AddonKey key = new AddonKey(views, addonId); - if (!map.containsKey(key)) - map.put(key, ModuleIdentifier.fromString(toModuleId(addonId) + "_" + UUID.randomUUID().toString())); - return map.get(key); + if (!map.containsKey(addon)) + map.put(addon, ModuleIdentifier.fromString(toModuleId(addon.getId()) + "_" + UUID.randomUUID().toString())); + return map.get(addon); } private String toModuleId(AddonId id) @@ -47,10 +45,10 @@ private String toModuleId(AddonId id) public String toString() { StringBuilder builder = new StringBuilder(); - Iterator> iterator = map.entrySet().iterator(); + Iterator> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { - Entry entry = iterator.next(); + Entry entry = iterator.next(); builder.append(entry.getKey()).append(" -> ").append(entry.getValue()); if (iterator.hasNext()) builder.append("\n"); @@ -58,61 +56,4 @@ public String toString() return builder.toString(); } - public class AddonKey - { - private Set views; - private AddonId addonId; - - public AddonKey(Set views, AddonId addonId) - { - this.views = views; - this.addonId = addonId; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + getOuterType().hashCode(); - result = prime * result + ((addonId == null) ? 0 : addonId.hashCode()); - result = prime * result + ((views == null) ? 0 : views.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AddonKey other = (AddonKey) obj; - if (!getOuterType().equals(other.getOuterType())) - return false; - if (addonId == null) - { - if (other.addonId != null) - return false; - } - else if (!addonId.equals(other.addonId)) - return false; - if (views == null) - { - if (other.views != null) - return false; - } - else if (!views.equals(other.views)) - return false; - return true; - } - - private AddonModuleIdentifierCache getOuterType() - { - return AddonModuleIdentifierCache.this; - } - - } } diff --git a/container/src/main/java/org/jboss/forge/furnace/modules/AddonModuleLoader.java b/container/src/main/java/org/jboss/forge/furnace/modules/AddonModuleLoader.java index 42027664..65e9cb8e 100644 --- a/container/src/main/java/org/jboss/forge/furnace/modules/AddonModuleLoader.java +++ b/container/src/main/java/org/jboss/forge/furnace/modules/AddonModuleLoader.java @@ -16,8 +16,10 @@ import java.util.logging.Logger; import org.jboss.forge.furnace.Furnace; +import org.jboss.forge.furnace.addons.Addon; import org.jboss.forge.furnace.addons.AddonId; import org.jboss.forge.furnace.addons.AddonLifecycleManager; +import org.jboss.forge.furnace.addons.AddonStateManager; import org.jboss.forge.furnace.addons.AddonView; import org.jboss.forge.furnace.exception.ContainerException; import org.jboss.forge.furnace.impl.AddonRepositoryImpl; @@ -28,6 +30,7 @@ import org.jboss.forge.furnace.modules.providers.XPathJDKClasspathSpec; import org.jboss.forge.furnace.repositories.AddonDependencyEntry; import org.jboss.forge.furnace.repositories.AddonRepository; +import org.jboss.forge.furnace.versions.Version; import org.jboss.modules.DependencySpec; import org.jboss.modules.Module; import org.jboss.modules.ModuleIdentifier; @@ -51,34 +54,40 @@ public class AddonModuleLoader extends ModuleLoader private AddonModuleIdentifierCache moduleCache; private AddonModuleJarFileCache moduleJarFileCache; - private AddonLifecycleManager manager; + private AddonLifecycleManager lifecycleManager; + private AddonStateManager stateManager; - private ThreadLocal currentView = new ThreadLocal(); - private ThreadLocal> currentViews = new ThreadLocal>(); + private ThreadLocal currentAddon = new ThreadLocal(); - public AddonModuleLoader(Furnace furnace, AddonLifecycleManager manager) + public AddonModuleLoader(Furnace furnace, AddonLifecycleManager lifecycleManager, AddonStateManager stateManager) { - this.manager = manager; + this.lifecycleManager = lifecycleManager; + this.stateManager = stateManager; this.moduleCache = new AddonModuleIdentifierCache(); this.moduleJarFileCache = new AddonModuleJarFileCache(); - moduleProviders = ServiceLoader.load(ModuleSpecProvider.class, furnace.getRuntimeClassLoader()); + this.moduleProviders = ServiceLoader.load(ModuleSpecProvider.class, furnace.getRuntimeClassLoader()); installModuleMBeanServer(); } /** - * Installs the MBeanServer. + * Loads a module for the given Addon. */ - private void installModuleMBeanServer() + public final Module loadAddonModule(Addon addon) throws ModuleLoadException { try { - Method method = ModuleLoader.class.getDeclaredMethod("installMBeanServer"); - method.setAccessible(true); - method.invoke(null); + this.currentAddon.set(addon); + ModuleIdentifier moduleId = moduleCache.getModuleId(addon); + Module result = loadModule(moduleId); + return result; } - catch (Exception e) + catch (ModuleLoadException e) { - throw new ContainerException("Could not install Modules MBean server", e); + throw e; + } + finally + { + this.currentAddon.remove(); } } @@ -92,39 +101,16 @@ protected Module preloadModule(ModuleIdentifier identifier) throws ModuleLoadExc @Override protected ModuleSpec findModule(ModuleIdentifier id) throws ModuleLoadException { - ModuleSpec result = findAddonModule(id); + ModuleSpec result = null; + if (currentAddon.get() != null) + result = findAddonModule(id); + if (result == null) result = findRegularModule(id); return result; } - /** - * Loads a module from the current {@link AddonView} based on the {@link AddonId} - * - * @param views - */ - public final Module loadModule(Set views, AddonView view, AddonId addonId) throws ModuleLoadException - { - try - { - this.currentView.set(view); - this.currentViews.set(views); - ModuleIdentifier moduleId = moduleCache.getModuleId(views, addonId); - Module result = loadModule(moduleId); - return result; - } - catch (ModuleLoadException e) - { - throw e; - } - finally - { - this.currentView.remove(); - this.currentViews.remove(); - } - } - private ModuleSpec findRegularModule(ModuleIdentifier id) { ModuleSpec result = null; @@ -139,9 +125,10 @@ private ModuleSpec findRegularModule(ModuleIdentifier id) public ModuleSpec findAddonModule(ModuleIdentifier id) { - for (AddonRepository repository : manager.getRepositories()) + Set views = stateManager.getViewsOf(currentAddon.get()); + for (AddonRepository repository : views.iterator().next().getRepositories()) { - AddonId found = findInstalledModule(repository, id); + AddonId found = findInstalledModule(views, repository, id); if (found != null) { @@ -163,7 +150,7 @@ public ModuleSpec findAddonModule(ModuleIdentifier id) PathFilters.acceptAll())); try { - addAddonDependencies(repository, found, builder); + addAddonDependencies(views, repository, found, builder); } catch (ContainerException e) { @@ -213,16 +200,17 @@ else if (file.length() > 0) } } - private void addAddonDependencies(AddonRepository repository, AddonId found, Builder builder) + private void addAddonDependencies(Set views, AddonRepository repository, AddonId found, Builder builder) throws ContainerException { Set addons = repository.getAddonDependencies(found); for (AddonDependencyEntry dependency : addons) { - AddonId addonId = manager.resolve(this.currentView.get(), dependency.getName()); + AddonId addonId = stateManager.resolveAddonId(views, dependency.getName()); ModuleIdentifier moduleId = null; if (addonId != null) { + Addon addon = lifecycleManager.getAddon(views, addonId); moduleId = findCompatibleInstalledModule(addonId); if (moduleId != null) { @@ -230,7 +218,7 @@ private void addAddonDependencies(AddonRepository repository, AddonId found, Bui PathFilters.not(PathFilters.getMetaInfFilter()), dependency.isExported() ? PathFilters.acceptAll() : PathFilters.rejectAll(), this, - moduleCache.getModuleId(this.currentViews.get(), addonId), + moduleCache.getModuleId(addon), dependency.isOptional())); } } @@ -241,18 +229,21 @@ private void addAddonDependencies(AddonRepository repository, AddonId found, Bui } } - private AddonId findInstalledModule(AddonRepository repository, ModuleIdentifier moduleId) + private AddonId findInstalledModule(Set views, AddonRepository repository, ModuleIdentifier moduleId) { AddonId found = null; + List enabled = repository.listEnabledCompatibleWithVersion(AddonRepositoryImpl.getRuntimeAPIVersion()); - for (AddonId addon : enabled) + for (AddonId id : enabled) { - if (moduleCache.getModuleId(this.currentViews.get(), addon).equals(moduleId)) + Addon addon = lifecycleManager.getAddon(views, id); + if (moduleCache.getModuleId(addon).equals(moduleId)) { - found = addon; + found = id; break; } } + return found; } @@ -260,15 +251,16 @@ private ModuleIdentifier findCompatibleInstalledModule(AddonId addonId) { ModuleIdentifier result = null; - ALL: for (AddonRepository repository : manager.getRepositories()) + Addon addon = currentAddon.get(); + Version runtimeAPIVersion = AddonRepositoryImpl.getRuntimeAPIVersion(); + + AddonRepository repository = stateManager.getViewsOf(addon).iterator().next().getRepositories().iterator().next(); + List enabled = repository.listEnabledCompatibleWithVersion(runtimeAPIVersion); + for (AddonId id : enabled) { - for (AddonId id : repository.listEnabledCompatibleWithVersion(AddonRepositoryImpl.getRuntimeAPIVersion())) + if (id.getName().equals(addonId.getName())) { - if (id.getName().equals(addonId.getName())) - { - result = moduleCache.getModuleId(this.currentViews.get(), id); - break ALL; - } + result = moduleCache.getModuleId(addon); } } @@ -281,11 +273,28 @@ public String toString() return "AddonModuleLoader"; } - public void releaseAddonModule(Set views, AddonId addonId) + public void releaseAddonModule(Addon addon) { - ModuleIdentifier id = moduleCache.getModuleId(views, addonId); + ModuleIdentifier id = moduleCache.getModuleId(addon); moduleJarFileCache.closeJarFileReferences(id); - moduleCache.clear(views, addonId); + moduleCache.clear(addon); + } + + /** + * Installs the MBeanServer. + */ + private void installModuleMBeanServer() + { + try + { + Method method = ModuleLoader.class.getDeclaredMethod("installMBeanServer"); + method.setAccessible(true); + method.invoke(null); + } + catch (Exception e) + { + throw new ContainerException("Could not install Modules MBean server", e); + } } } diff --git a/container/src/main/java/org/jboss/forge/furnace/util/CompletedFuture.java b/container/src/main/java/org/jboss/forge/furnace/util/NullFuture.java similarity index 92% rename from container/src/main/java/org/jboss/forge/furnace/util/CompletedFuture.java rename to container/src/main/java/org/jboss/forge/furnace/util/NullFuture.java index 41ca340c..fd2672f4 100644 --- a/container/src/main/java/org/jboss/forge/furnace/util/CompletedFuture.java +++ b/container/src/main/java/org/jboss/forge/furnace/util/NullFuture.java @@ -16,11 +16,11 @@ * * @author Lincoln Baxter, III */ -public class CompletedFuture implements Future +public class NullFuture implements Future { private T value; - public CompletedFuture(T value) + public NullFuture(T value) { super(); this.value = value;