diff --git a/manager/impl/src/main/java/org/jboss/forge/furnace/manager/impl/request/AbstractAddonActionRequest.java b/manager/impl/src/main/java/org/jboss/forge/furnace/manager/impl/request/AbstractAddonActionRequest.java index 71ea3918..39a09a1c 100644 --- a/manager/impl/src/main/java/org/jboss/forge/furnace/manager/impl/request/AbstractAddonActionRequest.java +++ b/manager/impl/src/main/java/org/jboss/forge/furnace/manager/impl/request/AbstractAddonActionRequest.java @@ -55,20 +55,21 @@ public final void perform() try { execute(); - if (!furnace.getStatus().isStopped()) - { - while (furnace.getStatus().isStarting() || !listener.isConfigurationScanned()) + if (!Boolean.getBoolean("forge.repo.skip_enable")) + if (!furnace.getStatus().isStopped()) { - try + while (furnace.getStatus().isStarting() || !listener.isConfigurationScanned()) { - Thread.sleep(100); - } - catch (InterruptedException e) - { - throw new RuntimeException(e); + try + { + Thread.sleep(100); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } } } - } } finally { diff --git a/manager/impl/src/main/java/org/jboss/forge/furnace/manager/impl/request/DeployRequestImpl.java b/manager/impl/src/main/java/org/jboss/forge/furnace/manager/impl/request/DeployRequestImpl.java index 64a38cf7..72c924cd 100644 --- a/manager/impl/src/main/java/org/jboss/forge/furnace/manager/impl/request/DeployRequestImpl.java +++ b/manager/impl/src/main/java/org/jboss/forge/furnace/manager/impl/request/DeployRequestImpl.java @@ -46,32 +46,28 @@ public void execute() @Override public Object call() throws Exception { - deploy(repository); - repository.enable(addonInfo.getAddon()); + AddonId addon = addonInfo.getAddon(); + Set resourceJars = addonInfo.getResources(); + + if (resourceJars.isEmpty()) + { + log.fine("No resource JARs found for " + addon); + } + + Set addonDependencies = addonInfo.getDependencyEntries(); + if (addonDependencies.isEmpty()) + { + log.fine("No dependencies found for addon " + addon); + } + log.info("Deploying addon " + addon); + repository.deploy(addon, addonDependencies, resourceJars); + if (!Boolean.getBoolean("forge.repo.skip_enable")) + repository.enable(addonInfo.getAddon()); return null; } }); } - protected void deploy(MutableAddonRepository repository) - { - AddonId addon = addonInfo.getAddon(); - Set resourceJars = addonInfo.getResources(); - - if (resourceJars.isEmpty()) - { - log.fine("No resource JARs found for " + addon); - } - - Set addonDependencies = addonInfo.getDependencyEntries(); - if (addonDependencies.isEmpty()) - { - log.fine("No dependencies found for addon " + addon); - } - log.info("Deploying addon " + addon); - repository.deploy(addon, addonDependencies, resourceJars); - } - @Override public String toString() { diff --git a/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/AggregateDeploymentStrategy.java b/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/AggregateDeploymentStrategy.java new file mode 100644 index 00000000..caff42d6 --- /dev/null +++ b/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/AggregateDeploymentStrategy.java @@ -0,0 +1,207 @@ +/* + * Copyright 2013 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Eclipse Public License version 1.0, available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.jboss.forge.arquillian; + +import java.io.File; +import java.util.ArrayList; +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.arquillian.container.spi.client.container.DeploymentException; +import org.jboss.arquillian.container.spi.client.deployment.Deployment; +import org.jboss.forge.arquillian.archive.ForgeArchive; +import org.jboss.forge.arquillian.archive.ForgeRemoteAddon; +import org.jboss.forge.arquillian.util.FurnaceUtil; +import org.jboss.forge.arquillian.util.ShrinkWrapUtil; +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.AddonRegistry; +import org.jboss.forge.furnace.lock.LockMode; +import org.jboss.forge.furnace.manager.AddonManager; +import org.jboss.forge.furnace.manager.impl.AddonManagerImpl; +import org.jboss.forge.furnace.manager.maven.addon.MavenAddonDependencyResolver; +import org.jboss.forge.furnace.manager.request.InstallRequest; +import org.jboss.forge.furnace.manager.spi.AddonDependencyResolver; +import org.jboss.forge.furnace.manager.spi.AddonInfo; +import org.jboss.forge.furnace.repositories.AddonRepository; +import org.jboss.forge.furnace.repositories.MutableAddonRepository; +import org.jboss.forge.furnace.util.Addons; +import org.jboss.shrinkwrap.api.Archive; + +/** + * @author Lincoln Baxter, III + * + */ +public class AggregateDeploymentStrategy implements DeploymentStrategyType +{ + boolean enabled = false; + private Map> deployed = new HashMap>(); + + @Override + public void beforeTestMethodExecution(final Furnace furnace) throws DeploymentException + { + if (!enabled) + { + enabled = true; + FurnaceUtil.waitForConfigurationRescan(furnace, new Callable() + { + @Override + public Void call() throws Exception + { + return furnace.getLockManager().performLocked(LockMode.WRITE, new Callable() + { + @Override + public Void call() throws Exception + { + for (AddonRepository repo : furnace.getRepositories()) + { + if (repo instanceof MutableAddonRepository) + { + Set addons = getAddonsFor((MutableAddonRepository) repo); + for (AddonId addonId : addons) + { + ((MutableAddonRepository) repo).enable(addonId); + } + } + } + return null; + } + }); + } + }); + + for (AddonRepository repo : deployed.keySet()) + { + if (repo instanceof MutableAddonRepository) + { + Set addons = getAddonsFor((MutableAddonRepository) repo); + for (AddonId addonId : addons) + { + waitForDeploymentCompletion(furnace, addonId); + } + } + } + } + } + + private Set getAddonsFor(MutableAddonRepository repo) + { + if (deployed.get(repo) == null) + deployed.put(repo, new HashSet()); + return deployed.get(repo); + } + + private void waitForDeploymentCompletion(Furnace furnace, final AddonId addonToDeploy) + throws DeploymentException + { + AddonRegistry registry = furnace.getAddonRegistry(); + Addon addon = registry.getAddon(addonToDeploy); + try + { + Future future = addon.getFuture(); + future.get(); + if (addon.getStatus().isFailed()) + { + throw new DeploymentException("AddonDependency " + addonToDeploy + " failed to deploy."); + } + } + catch (Exception e) + { + throw new DeploymentException("AddonDependency " + addonToDeploy + " failed to deploy.", e); + } + } + + @Override + public void deploy(Furnace furnace, + final MutableAddonRepository repository, + final Deployment deployment, + final Archive archive, + final AddonId addonToDeploy) throws DeploymentException + { + if (archive instanceof ForgeArchive) + { + System.out.println("Deploying [" + addonToDeploy + "] to repository [" + repository + "]"); + File destDir = repository.getAddonBaseDir(addonToDeploy); + destDir.mkdirs(); + ShrinkWrapUtil.toFile(new File(destDir.getAbsolutePath(), archive.getName()), archive); + ShrinkWrapUtil.unzip(destDir, archive); + repository.deploy(addonToDeploy, ((ForgeArchive) archive).getAddonDependencies(), new ArrayList()); + addDeployedAddon(repository, addonToDeploy); + } + else if (archive instanceof ForgeRemoteAddon) + { + ForgeRemoteAddon remoteAddon = (ForgeRemoteAddon) archive; + AddonDependencyResolver resolver = new MavenAddonDependencyResolver(); + AddonManager addonManager = new AddonManagerImpl(furnace, resolver); + InstallRequest request = addonManager.install(remoteAddon.getAddonId(), repository); + System.setProperty("forge.repo.skip_enable", "true"); + try + { + request.perform(); + } + finally + { + System.setProperty("forge.repo.skip_enable", "false"); + } + addDeployedAddons(repository, request.getRequestedAddonInfo()); + } + else + { + throw new IllegalArgumentException( + "Invalid Archive type. Ensure that your @Deployment method returns type 'ForgeArchive'."); + } + } + + private void addDeployedAddon(final MutableAddonRepository repository, final AddonId addonToDeploy) + { + getAddonsFor(repository).add(addonToDeploy); + } + + private void addDeployedAddons(MutableAddonRepository repository, AddonInfo info) + { + Set addons = getAddonsFor(repository); + for (AddonInfo i : info.getOptionalAddons()) + { + addDeployedAddons(repository, i); + } + for (AddonInfo i : info.getRequiredAddons()) + { + addDeployedAddons(repository, i); + } + addons.add(info.getAddon()); + } + + @Override + public void undeploy(Furnace furnace, MutableAddonRepository repository, AddonId addonToUndeploy) + throws DeploymentException + { + AddonRegistry registry = furnace.getAddonRegistry(); + System.out.println("Undeploying [" + addonToUndeploy + "] ... "); + + try + { + Addon addonToStop = registry.getAddon(addonToUndeploy); + if (addonToStop.getStatus().isLoaded()) + ((MutableAddonRepository) addonToStop.getRepository()).disable(addonToUndeploy); + Addons.waitUntilStopped(addonToStop); + } + catch (Exception e) + { + throw new DeploymentException("Failed to undeploy " + addonToUndeploy, e); + } + finally + { + repository.undeploy(addonToUndeploy); + } + } + +} diff --git a/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/ForgeDeployableContainer.java b/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/ForgeDeployableContainer.java index 643858d8..aa102118 100644 --- a/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/ForgeDeployableContainer.java +++ b/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/ForgeDeployableContainer.java @@ -8,13 +8,11 @@ import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Future; import org.jboss.arquillian.container.spi.client.container.DeployableContainer; import org.jboss.arquillian.container.spi.client.container.DeploymentException; @@ -24,29 +22,18 @@ import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData; import org.jboss.arquillian.core.api.Instance; import org.jboss.arquillian.core.api.annotation.Inject; -import org.jboss.forge.arquillian.archive.ForgeArchive; -import org.jboss.forge.arquillian.archive.ForgeRemoteAddon; -import org.jboss.forge.arquillian.archive.RepositoryForgeArchive; +import org.jboss.forge.arquillian.archive.DeploymentTypeSelector; +import org.jboss.forge.arquillian.archive.RepositorySelector; import org.jboss.forge.arquillian.protocol.ForgeProtocolDescription; import org.jboss.forge.arquillian.protocol.FurnaceHolder; -import org.jboss.forge.arquillian.util.ShrinkWrapUtil; +import org.jboss.forge.arquillian.util.FurnaceUtil; 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.AddonRegistry; import org.jboss.forge.furnace.impl.FurnaceImpl; import org.jboss.forge.furnace.impl.util.Files; -import org.jboss.forge.furnace.manager.AddonManager; -import org.jboss.forge.furnace.manager.impl.AddonManagerImpl; -import org.jboss.forge.furnace.manager.maven.addon.MavenAddonDependencyResolver; -import org.jboss.forge.furnace.manager.spi.AddonDependencyResolver; import org.jboss.forge.furnace.repositories.AddonRepository; import org.jboss.forge.furnace.repositories.AddonRepositoryMode; import org.jboss.forge.furnace.repositories.MutableAddonRepository; -import org.jboss.forge.furnace.spi.ContainerLifecycleListener; -import org.jboss.forge.furnace.spi.ListenerRegistration; -import org.jboss.forge.furnace.util.Addons; -import org.jboss.forge.furnace.util.Callables; import org.jboss.forge.furnace.util.ClassLoaders; import org.jboss.forge.furnace.util.OperatingSystemUtils; import org.jboss.shrinkwrap.api.Archive; @@ -75,7 +62,6 @@ public class ForgeDeployableContainer implements DeployableContainer archive) throws DeploymentException { - Deployment deployment = deploymentInstance.get(); final AddonId addonToDeploy = getAddonEntry(deployment); @@ -85,75 +71,44 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept cleanup(); } - if (archive instanceof ForgeArchive) - { - final MutableAddonRepository target = selectTargetRepository(archive); - - waitForConfigurationRescan(new Callable() - { - @Override - public Void call() throws Exception - { - deployToRepository(archive, target, addonToDeploy); - return null; - } - }); - - waitForDeploymentCompletion(deployment, addonToDeploy); - } - else if (archive instanceof ForgeRemoteAddon) - { - ForgeRemoteAddon remoteAddon = (ForgeRemoteAddon) archive; - AddonDependencyResolver resolver = new MavenAddonDependencyResolver(); - AddonManager addonManager = new AddonManagerImpl(runnable.furnace, resolver); - - AddonRepository target = selectTargetRepository(archive); - addonManager.install(remoteAddon.getAddonId(), target).perform(); - - waitForDeploymentCompletion(deployment, addonToDeploy); - } - else - { - throw new IllegalArgumentException( - "Invalid Archive type. Ensure that your @Deployment method returns type 'ForgeArchive'."); - } + final MutableAddonRepository target = selectTargetRepository(archive); + DeploymentStrategyType strategy = selectDeploymentStrategy(archive); + strategy.deploy(runnable.furnace, target, deployment, archive, addonToDeploy); return new ProtocolMetaData().addContext(furnaceHolder); } - private T waitForConfigurationRescan(Callable action) + private DeploymentStrategyType selectDeploymentStrategy(Archive archive) { + Strategy strategyType = ((DeploymentTypeSelector) archive).getDeploymentStrategyType(); + DeploymentStrategyType result = null; + switch (strategyType) + { + case ISOLATED: + result = new IsolatedDeploymentStrategy(); + break; - ConfigurationScanListener listener = new ConfigurationScanListener(); - ListenerRegistration registration = runnable.furnace - .addContainerLifecycleListener(listener); - - T result = Callables.call(action); + case AGGREGATE: + result = new AggregateDeploymentStrategy(); + break; - while (runnable.furnace.getStatus().isStarting() || !listener.isConfigurationScanned()) - { - try - { - Thread.sleep(100); - } - catch (InterruptedException e) - { - throw new RuntimeException("Sleep interrupted while waiting for configuration rescan.", e); - } + default: + break; } - registration.removeListener(); + if (furnaceHolder.getDeploymentStrategy() == null) + furnaceHolder.setDeploymentStrategy(result); - return result; + return furnaceHolder.getDeploymentStrategy(); } private MutableAddonRepository selectTargetRepository(Archive archive) { MutableAddonRepository target = repository; - if (archive instanceof RepositoryForgeArchive - && ((RepositoryForgeArchive) archive).getAddonRepository() != null) + if (archive instanceof RepositorySelector + && ((RepositorySelector) archive).getAddonRepository() != null) { - String repositoryName = ((RepositoryForgeArchive) archive).getAddonRepository(); + String repositoryName = ((RepositorySelector) archive).getAddonRepository(); if (deploymentRepositories.get(repositoryName) == null) { stopContainer(); @@ -176,46 +131,12 @@ private MutableAddonRepository selectTargetRepository(Archive archive) return target; } - private void waitForDeploymentCompletion(Deployment deployment, final AddonId addonToDeploy) - throws DeploymentException - { - AddonRegistry registry = runnable.getForge().getAddonRegistry(); - Addon addon = registry.getAddon(addonToDeploy); - try - { - Future future = addon.getFuture(); - future.get(); - if (addon.getStatus().isFailed()) - { - DeploymentException e = new DeploymentException("AddonDependency " + addonToDeploy - + " failed to deploy."); - deployment.deployedWithError(e); - throw new DeploymentException("AddonDependency " + addonToDeploy + " failed to deploy.", e); - } - } - catch (Exception e) - { - deployment.deployedWithError(e); - throw new DeploymentException("AddonDependency " + addonToDeploy + " failed to deploy.", e); - } - } - - private void deployToRepository(Archive archive, MutableAddonRepository repository, final AddonId addonToDeploy) - { - File destDir = repository.getAddonBaseDir(addonToDeploy); - destDir.mkdirs(); - ShrinkWrapUtil.toFile(new File(destDir.getAbsolutePath(), archive.getName()), archive); - ShrinkWrapUtil.unzip(destDir, archive); - System.out.println("Deploying [" + addonToDeploy + "] to repository [" + repository + "]"); - repository.deploy(addonToDeploy, ((ForgeArchive) archive).getAddonDependencies(), new ArrayList()); - repository.enable(addonToDeploy); - } - private void cleanup() { try { deploymentRepositories.clear(); + furnaceHolder.setDeploymentStrategy(null); stop(); start(); } @@ -290,7 +211,7 @@ public void start() throws LifecycleException private void startContainer() { - waitForConfigurationRescan(new Callable() + FurnaceUtil.waitForConfigurationRescan(runnable.furnace, new Callable() { @Override public Void call() throws Exception @@ -326,24 +247,8 @@ public void undeploy(Archive archive) throws DeploymentException { undeploying = true; AddonId addonToUndeploy = getAddonEntry(deploymentInstance.get()); - AddonRegistry registry = runnable.getForge().getAddonRegistry(); - System.out.println("Undeploying [" + addonToUndeploy + "] ... "); - - try - { - Addon addonToStop = registry.getAddon(addonToUndeploy); - if (addonToStop.getStatus().isLoaded()) - ((MutableAddonRepository) addonToStop.getRepository()).disable(addonToUndeploy); - Addons.waitUntilStopped(addonToStop); - } - catch (Exception e) - { - throw new DeploymentException("Failed to undeploy " + addonToUndeploy, e); - } - finally - { - repository.undeploy(addonToUndeploy); - } + DeploymentStrategyType strategy = selectDeploymentStrategy(archive); + strategy.undeploy(runnable.getForge(), repository, addonToUndeploy); } @Override diff --git a/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/IsolatedDeploymentStrategy.java b/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/IsolatedDeploymentStrategy.java new file mode 100644 index 00000000..6301d467 --- /dev/null +++ b/test-harness/arquillian/classpath/src/main/java/org/jboss/forge/arquillian/IsolatedDeploymentStrategy.java @@ -0,0 +1,139 @@ +/* + * Copyright 2013 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Eclipse Public License version 1.0, available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.jboss.forge.arquillian; + +import java.io.File; +import java.util.ArrayList; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; + +import org.jboss.arquillian.container.spi.client.container.DeploymentException; +import org.jboss.arquillian.container.spi.client.deployment.Deployment; +import org.jboss.forge.arquillian.archive.ForgeArchive; +import org.jboss.forge.arquillian.archive.ForgeRemoteAddon; +import org.jboss.forge.arquillian.util.FurnaceUtil; +import org.jboss.forge.arquillian.util.ShrinkWrapUtil; +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.AddonRegistry; +import org.jboss.forge.furnace.manager.AddonManager; +import org.jboss.forge.furnace.manager.impl.AddonManagerImpl; +import org.jboss.forge.furnace.manager.maven.addon.MavenAddonDependencyResolver; +import org.jboss.forge.furnace.manager.spi.AddonDependencyResolver; +import org.jboss.forge.furnace.repositories.MutableAddonRepository; +import org.jboss.forge.furnace.util.Addons; +import org.jboss.shrinkwrap.api.Archive; + +/** + * @author Lincoln Baxter, III + * + */ +public class IsolatedDeploymentStrategy implements DeploymentStrategyType +{ + + @Override + public void beforeTestMethodExecution(Furnace furnace) + { + } + + @Override + public void deploy(Furnace furnace, + final MutableAddonRepository target, + final Deployment deployment, + final Archive archive, + final AddonId addonToDeploy) throws DeploymentException + { + if (archive instanceof ForgeRemoteAddon) + { + ForgeRemoteAddon remoteAddon = (ForgeRemoteAddon) archive; + AddonDependencyResolver resolver = new MavenAddonDependencyResolver(); + AddonManager addonManager = new AddonManagerImpl(furnace, resolver); + addonManager.install(remoteAddon.getAddonId(), target).perform(); + waitForDeploymentCompletion(furnace, deployment, addonToDeploy); + } + else if (archive instanceof ForgeArchive) + { + FurnaceUtil.waitForConfigurationRescan(furnace, new Callable() + { + @Override + public Void call() throws Exception + { + deployToRepository(archive, target, addonToDeploy); + return null; + } + }); + + waitForDeploymentCompletion(furnace, deployment, addonToDeploy); + } + else + { + throw new IllegalArgumentException( + "Invalid Archive type. Ensure that your @Deployment method returns type 'ForgeArchive'."); + } + } + + private void waitForDeploymentCompletion(Furnace furnace, Deployment deployment, final AddonId addonToDeploy) + throws DeploymentException + { + AddonRegistry registry = furnace.getAddonRegistry(); + Addon addon = registry.getAddon(addonToDeploy); + try + { + Future future = addon.getFuture(); + future.get(); + if (addon.getStatus().isFailed()) + { + DeploymentException e = new DeploymentException("AddonDependency " + addonToDeploy + + " failed to deploy."); + deployment.deployedWithError(e); + throw new DeploymentException("AddonDependency " + addonToDeploy + " failed to deploy.", e); + } + } + catch (Exception e) + { + deployment.deployedWithError(e); + throw new DeploymentException("AddonDependency " + addonToDeploy + " failed to deploy.", e); + } + } + + private void deployToRepository(Archive archive, MutableAddonRepository repository, final AddonId addonToDeploy) + { + System.out.println("Deploying [" + addonToDeploy + "] to repository [" + repository + "]"); + File destDir = repository.getAddonBaseDir(addonToDeploy); + destDir.mkdirs(); + ShrinkWrapUtil.toFile(new File(destDir.getAbsolutePath(), archive.getName()), archive); + ShrinkWrapUtil.unzip(destDir, archive); + repository.deploy(addonToDeploy, ((ForgeArchive) archive).getAddonDependencies(), new ArrayList()); + repository.enable(addonToDeploy); + } + + @Override + public void undeploy(Furnace furnace, MutableAddonRepository repository, AddonId addonToUndeploy) + throws DeploymentException + { + AddonRegistry registry = furnace.getAddonRegistry(); + System.out.println("Undeploying [" + addonToUndeploy + "] ... "); + + try + { + Addon addonToStop = registry.getAddon(addonToUndeploy); + if (addonToStop.getStatus().isLoaded()) + ((MutableAddonRepository) addonToStop.getRepository()).disable(addonToUndeploy); + Addons.waitUntilStopped(addonToStop); + } + catch (Exception e) + { + throw new DeploymentException("Failed to undeploy " + addonToUndeploy, e); + } + finally + { + repository.undeploy(addonToUndeploy); + } + } + +} diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/DeploymentStrategy.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/DeploymentStrategy.java new file mode 100644 index 00000000..49a1855d --- /dev/null +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/DeploymentStrategy.java @@ -0,0 +1,15 @@ +package org.jboss.forge.arquillian; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface DeploymentStrategy +{ + Strategy value() default Strategy.ISOLATED; +} diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/DeploymentStrategyType.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/DeploymentStrategyType.java new file mode 100644 index 00000000..78aa4f2a --- /dev/null +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/DeploymentStrategyType.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Eclipse Public License version 1.0, available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.jboss.forge.arquillian; + +import org.jboss.arquillian.container.spi.client.container.DeploymentException; +import org.jboss.arquillian.container.spi.client.deployment.Deployment; +import org.jboss.forge.furnace.Furnace; +import org.jboss.forge.furnace.addons.AddonId; +import org.jboss.forge.furnace.repositories.MutableAddonRepository; +import org.jboss.shrinkwrap.api.Archive; + +/** + * @author Lincoln Baxter, III + * + */ +public interface DeploymentStrategyType +{ + void beforeTestMethodExecution(Furnace furnace) throws DeploymentException; + + void deploy(Furnace furnace, MutableAddonRepository target, Deployment deployment, Archive archive, + AddonId addonToDeploy) throws DeploymentException; + + void undeploy(Furnace furnace, MutableAddonRepository target, AddonId addonToUndeploy) throws DeploymentException; +} diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/ForgeDeploymentScenarioGenerator.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/ForgeDeploymentScenarioGenerator.java index a0bc6285..78d2efd8 100644 --- a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/ForgeDeploymentScenarioGenerator.java +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/ForgeDeploymentScenarioGenerator.java @@ -21,8 +21,9 @@ import org.jboss.arquillian.container.test.api.TargetsContainer; import org.jboss.arquillian.container.test.spi.client.deployment.DeploymentScenarioGenerator; import org.jboss.arquillian.test.spi.TestClass; +import org.jboss.forge.arquillian.archive.DeploymentTypeSelector; import org.jboss.forge.arquillian.archive.ForgeRemoteAddon; -import org.jboss.forge.arquillian.archive.RepositoryForgeArchive; +import org.jboss.forge.arquillian.archive.RepositorySelector; import org.jboss.forge.arquillian.maven.ProjectHelper; import org.jboss.forge.furnace.addons.AddonId; import org.jboss.forge.furnace.util.Annotations; @@ -42,16 +43,21 @@ public List generate(TestClass testClass) for (Method deploymentMethod : deploymentMethods) { validate(deploymentMethod); + Strategy strategy = Strategy.ISOLATED; + if (Annotations.isAnnotationPresent(testClass.getJavaClass(), DeploymentStrategy.class)) + { + strategy = Annotations.getAnnotation(testClass.getJavaClass(), DeploymentStrategy.class).value(); + } if (deploymentMethod.isAnnotationPresent(Dependencies.class)) - deployments.addAll(generateDependencyDeployments(testClass.getJavaClass(), deploymentMethod)); - deployments.add(generateDeployment(deploymentMethod)); + deployments.addAll(generateDependencyDeployments(testClass.getJavaClass(), deploymentMethod, strategy)); + deployments.add(generateDeployment(deploymentMethod, strategy)); } return deployments; } private Collection generateDependencyDeployments(Class classUnderTest, - Method deploymentMethod) + Method deploymentMethod, Strategy strategy) { Dependencies dependency = deploymentMethod.getAnnotation(Dependencies.class); Collection deployments = new ArrayList(); @@ -77,6 +83,7 @@ private Collection generateDependencyDeployments(Class } AddonId id = AddonId.from(addon.name(), version); ForgeRemoteAddon remoteAddon = ShrinkWrap.create(ForgeRemoteAddon.class).setAddonId(id); + remoteAddon.setDeploymentStrategyType(strategy); if (Annotations.isAnnotationPresent(deploymentMethod, DeployToRepository.class)) remoteAddon.setAddonRepository(Annotations.getAnnotation(deploymentMethod, DeployToRepository.class) @@ -176,9 +183,10 @@ private void validate(Method deploymentMethod) /** * @param deploymentMethod + * @param strategy * @return */ - private DeploymentDescription generateDeployment(Method deploymentMethod) + private DeploymentDescription generateDeployment(Method deploymentMethod, Strategy strategy) { TargetDescription target = generateTarget(deploymentMethod); ProtocolDescription protocol = generateProtocol(deploymentMethod); @@ -188,10 +196,14 @@ private DeploymentDescription generateDeployment(Method deploymentMethod) if (Archive.class.isAssignableFrom(deploymentMethod.getReturnType())) { Archive archive = invoke(Archive.class, deploymentMethod); - if (archive instanceof RepositoryForgeArchive) + if (archive instanceof DeploymentTypeSelector) + { + ((DeploymentTypeSelector) archive).setDeploymentStrategyType(strategy); + } + if (archive instanceof RepositorySelector) { if (Annotations.isAnnotationPresent(deploymentMethod, DeployToRepository.class)) - ((RepositoryForgeArchive) archive).setAddonRepository(Annotations.getAnnotation(deploymentMethod, + ((RepositorySelector) archive).setAddonRepository(Annotations.getAnnotation(deploymentMethod, DeployToRepository.class).value()); } description = new DeploymentDescription(deploymentAnnotation.name(), archive); diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/ForgeTestMethodExecutor.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/ForgeTestMethodExecutor.java index 95fd75bf..39afdd95 100644 --- a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/ForgeTestMethodExecutor.java +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/ForgeTestMethodExecutor.java @@ -10,6 +10,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import org.jboss.arquillian.container.spi.client.container.DeploymentException; import org.jboss.arquillian.container.test.spi.ContainerMethodExecutor; import org.jboss.arquillian.test.spi.TestMethodExecutor; import org.jboss.arquillian.test.spi.TestResult; @@ -31,7 +32,8 @@ */ public class ForgeTestMethodExecutor implements ContainerMethodExecutor { - private Furnace forge; + private Furnace furnace; + private DeploymentStrategyType strategy; public ForgeTestMethodExecutor(ForgeProtocolConfiguration config, final FurnaceHolder holder) { @@ -43,7 +45,8 @@ public ForgeTestMethodExecutor(ForgeProtocolConfiguration config, final FurnaceH { throw new IllegalArgumentException("Furnace runtime must be provided"); } - this.forge = holder.getFurnace(); + this.furnace = holder.getFurnace(); + this.strategy = holder.getDeploymentStrategy(); } @Override @@ -54,14 +57,23 @@ public TestResult invoke(final TestMethodExecutor testMethodExecutor) throw new IllegalArgumentException("TestMethodExecutor must be specified"); } + try + { + strategy.beforeTestMethodExecution(furnace); + } + catch (DeploymentException e) + { + return new TestResult(Status.FAILED, e); + } + Object testInstance = null; Class testClass = null; try { final String testClassName = testMethodExecutor.getInstance().getClass().getName(); - final AddonRegistry addonRegistry = forge.getAddonRegistry(); + final AddonRegistry addonRegistry = furnace.getAddonRegistry(); - waitUntilStable(forge); + waitUntilStable(furnace); System.out.println("Searching for test [" + testClassName + "]"); for (Addon addon : addonRegistry.getAddons()) diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/Strategy.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/Strategy.java new file mode 100644 index 00000000..a55013f7 --- /dev/null +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/Strategy.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Eclipse Public License version 1.0, available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.jboss.forge.arquillian; + +import org.jboss.arquillian.container.test.api.ShouldThrowException; + +/** + * @author Lincoln Baxter, III + */ +public enum Strategy +{ + /** + * {@link AddonDependency} instances are deployed and enabled one at a time, and deployment success or failure is + * reported during deployment. This {@link Strategy} should be used when addon deployment order or deployment + * verification via {@link ShouldThrowException} is required. + */ + ISOLATED, + + /** + * {@link AddonDependency} instances are deployed one at a time, but enabled as a group. This strategy results in + * faster tests, but should be used when a simple success or failure result is acceptable. + */ + AGGREGATE +} diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/DeploymentTypeSelector.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/DeploymentTypeSelector.java new file mode 100644 index 00000000..df4b0367 --- /dev/null +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/DeploymentTypeSelector.java @@ -0,0 +1,13 @@ +package org.jboss.forge.arquillian.archive; + +import org.jboss.forge.arquillian.Strategy; + +/** + * @author Lincoln Baxter, III + */ +public interface DeploymentTypeSelector +{ + void setDeploymentStrategyType(Strategy strategy); + + Strategy getDeploymentStrategyType(); +} diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeArchiveImpl.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeArchiveImpl.java index 96b73d3a..6a90413a 100644 --- a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeArchiveImpl.java +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeArchiveImpl.java @@ -23,6 +23,7 @@ import java.util.Set; import java.util.logging.Logger; +import org.jboss.forge.arquillian.Strategy; import org.jboss.forge.arquillian.services.LocalServices; import org.jboss.forge.furnace.lifecycle.AddonLifecycleProvider; import org.jboss.forge.furnace.repositories.AddonDependencyEntry; @@ -37,7 +38,8 @@ /** * @author Lincoln Baxter, III */ -public class ForgeArchiveImpl extends ContainerBase implements ForgeArchive, RepositoryForgeArchive +public class ForgeArchiveImpl extends ContainerBase implements ForgeArchive, RepositorySelector, + DeploymentTypeSelector { // -------------------------------------------------------------------------------------|| // Class Members ----------------------------------------------------------------------|| @@ -193,7 +195,7 @@ public String getAddonRepository() } @Override - public RepositoryForgeArchive setAddonRepository(String repository) + public RepositorySelector setAddonRepository(String repository) { this.repository = repository; return this; @@ -217,4 +219,18 @@ public ForgeArchive addAsLocalServices(Class... serviceTypes) return this; } + private Strategy strategy; + + @Override + public void setDeploymentStrategyType(Strategy strategy) + { + this.strategy = strategy; + } + + @Override + public Strategy getDeploymentStrategyType() + { + return strategy; + } + } diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeRemoteAddon.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeRemoteAddon.java index b3028787..13960e7a 100644 --- a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeRemoteAddon.java +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeRemoteAddon.java @@ -8,13 +8,9 @@ * * @author Lincoln Baxter, III */ -public interface ForgeRemoteAddon extends Archive +public interface ForgeRemoteAddon extends Archive, RepositorySelector, DeploymentTypeSelector { AddonId getAddonId(); ForgeRemoteAddon setAddonId(AddonId id); - - String getAddonRepository(); - - ForgeRemoteAddon setAddonRepository(String repository); } diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeRemoteAddonImpl.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeRemoteAddonImpl.java index dfc7a6bb..7f987069 100644 --- a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeRemoteAddonImpl.java +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/ForgeRemoteAddonImpl.java @@ -16,6 +16,7 @@ */ package org.jboss.forge.arquillian.archive; +import org.jboss.forge.arquillian.Strategy; import org.jboss.forge.furnace.addons.AddonId; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ArchivePath; @@ -28,6 +29,7 @@ public class ForgeRemoteAddonImpl extends ContainerBase implem { private AddonId id; private String repository; + private Strategy strategy; @Override public AddonId getAddonId() @@ -60,6 +62,18 @@ public ForgeRemoteAddonImpl(Archive archive) super(ForgeRemoteAddon.class, archive); } + @Override + public Strategy getDeploymentStrategyType() + { + return strategy; + } + + @Override + public void setDeploymentStrategyType(Strategy strategy) + { + this.strategy = strategy; + } + @Override protected ArchivePath getClassesPath() { diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/RepositoryForgeArchive.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/RepositoryForgeArchive.java deleted file mode 100644 index bcd64287..00000000 --- a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/RepositoryForgeArchive.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.jboss.forge.arquillian.archive; - -/** - * Archive representing a Furnace AddonDependency deployment to be installed into a specific repository. - * - * @author Lincoln Baxter, III - */ -public interface RepositoryForgeArchive extends ForgeArchive -{ - String getAddonRepository(); - - RepositoryForgeArchive setAddonRepository(String repository); -} diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/RepositorySelector.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/RepositorySelector.java new file mode 100644 index 00000000..100bdea8 --- /dev/null +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/archive/RepositorySelector.java @@ -0,0 +1,11 @@ +package org.jboss.forge.arquillian.archive; + +/** + * @author Lincoln Baxter, III + */ +public interface RepositorySelector +{ + String getAddonRepository(); + + RepositorySelector setAddonRepository(String repository); +} diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/protocol/FurnaceHolder.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/protocol/FurnaceHolder.java index addbc936..05e36985 100644 --- a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/protocol/FurnaceHolder.java +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/protocol/FurnaceHolder.java @@ -6,6 +6,7 @@ */ package org.jboss.forge.arquillian.protocol; +import org.jboss.forge.arquillian.DeploymentStrategyType; import org.jboss.forge.furnace.Furnace; /** @@ -17,6 +18,7 @@ public class FurnaceHolder { private Furnace furnace; + private DeploymentStrategyType strategy; public Furnace getFurnace() { @@ -28,4 +30,14 @@ public void setFurnace(Furnace furnace) this.furnace = furnace; } + public DeploymentStrategyType getDeploymentStrategy() + { + return strategy; + } + + public void setDeploymentStrategy(DeploymentStrategyType strategy) + { + this.strategy = strategy; + } + } diff --git a/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/util/FurnaceUtil.java b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/util/FurnaceUtil.java new file mode 100644 index 00000000..26b14c40 --- /dev/null +++ b/test-harness/arquillian/core/src/main/java/org/jboss/forge/arquillian/util/FurnaceUtil.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Eclipse Public License version 1.0, available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.jboss.forge.arquillian.util; + +import java.util.concurrent.Callable; + +import org.jboss.forge.furnace.Furnace; +import org.jboss.forge.furnace.manager.impl.request.ConfigurationScanListener; +import org.jboss.forge.furnace.spi.ContainerLifecycleListener; +import org.jboss.forge.furnace.spi.ListenerRegistration; +import org.jboss.forge.furnace.util.Callables; + +/** + * @author Lincoln Baxter, III + * + */ +public class FurnaceUtil +{ + + public static T waitForConfigurationRescan(Furnace furnace, Callable action) + { + + ConfigurationScanListener listener = new ConfigurationScanListener(); + ListenerRegistration registration = furnace + .addContainerLifecycleListener(listener); + + T result = Callables.call(action); + + while (furnace.getStatus().isStarting() || !listener.isConfigurationScanned()) + { + try + { + Thread.sleep(100); + } + catch (InterruptedException e) + { + throw new RuntimeException("Sleep interrupted while waiting for configuration rescan.", e); + } + } + + registration.removeListener(); + + return result; + } +}