
org.fabric3.runtime.maven.itest.Fabric3ITestMojo Maven / Gradle / Ivy
/*
* Fabric3
* Copyright (c) 2009-2012 Metaform Systems
*
* Fabric3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version, with the
* following exception:
*
* Linking this software statically or dynamically with other
* modules is making a combined work based on this software.
* Thus, the terms and conditions of the GNU General Public
* License cover the whole combination.
*
* As a special exception, the copyright holders of this software
* give you permission to link this software with independent
* modules to produce an executable, regardless of the license
* terms of these independent modules, and to copy and distribute
* the resulting executable under terms of your choice, provided
* that you also meet, for each linked independent module, the
* terms and conditions of the license of that module. An
* independent module is a module which is not derived from or
* based on this software. If you modify this software, you may
* extend this exception to your version of the software, but
* you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version.
*
* Fabric3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the
* GNU General Public License along with Fabric3.
* If not, see .
*
* ----------------------------------------------------
*
* Portions originally based on Apache Tuscany 2007
* licensed under the Apache 2.0 license.
*
*/
package org.fabric3.runtime.maven.itest;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.execution.RuntimeInformation;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.fabric3.host.Names;
import org.fabric3.host.contribution.ContributionNotFoundException;
import org.fabric3.host.contribution.ContributionService;
import org.fabric3.host.contribution.ContributionSource;
import org.fabric3.host.contribution.FileContributionSource;
import org.fabric3.host.contribution.InstallException;
import org.fabric3.host.contribution.StoreException;
import org.fabric3.host.domain.DeploymentException;
import org.fabric3.host.domain.Domain;
import org.fabric3.host.classloader.DelegatingResourceClassLoader;
import org.fabric3.host.runtime.HiddenPackages;
import org.fabric3.host.classloader.MaskingClassLoader;
import org.fabric3.host.util.FileHelper;
import org.fabric3.runtime.maven.MavenRuntime;
/**
* Runs an embedded Fabric3 runtime for integration testing.
*
* @version $Rev: 11083 $ $Date: 2012-06-21 10:38:50 +0000 (Thu, 21 Jun 2012) $
* @goal test
* @phase integration-test
* @execute phase="integration-test"
*/
public class Fabric3ITestMojo extends AbstractMojo {
private static final String CLEAN = "fabric3.extensions.dependencies.cleanup";
static {
// This static block is used to optionally clean the temporary directory between test runs. A static block is used as the iTest plugin may
// be instantiated multiple times during a run.
boolean clearTmp = Boolean.valueOf(System.getProperty(CLEAN, "false"));
if (clearTmp) {
clearTempFiles();
}
}
/**
* POM
*
* @parameter expression="${project}"
* @readonly
* @required
*/
protected MavenProject project;
/**
* The optional target namespace of the composite to activate.
*
* @parameter
*/
public String compositeNamespace = "urn:fabric3.org";
/**
* The local name of the composite to activate.
*
* @parameter
*/
public String compositeName = "TestComposite";
/**
* The project build directory.
*
* @parameter expression="${project.build.directory}"
*/
public File buildDirectory;
/**
* Do not run if this is set to true. This usage is consistent with the surefire plugin.
*
* @parameter expression="${maven.test.skip}"
*/
public boolean skip;
/**
* The directory where reports will be written.
*
* @parameter expression="${project.build.directory}/surefire-reports"
*/
public File reportsDirectory;
/**
* Whether to trim the stack trace in the reports to just the lines within the test, or show the full trace.
*
* @parameter expression="${trimStackTrace}" default-value="true"
*/
public boolean trimStackTrace;
/**
* The version of the runtime to use.
*
* @parameter expression="RELEASE"
*/
public String runtimeVersion;
/**
* Set of contributions that should be deployed to the runtime.
*
* @parameter
*/
public Dependency[] contributions = new Dependency[0];
/**
* Set of runtime extension artifacts that should be deployed to the runtime.
*
* @parameter
*/
public Dependency[] extensions = new Dependency[0];
/**
* Set of profiles for the runtime.
*
* @parameter
*/
public Dependency[] profiles = new Dependency[0];
/**
* Libraries available to application and runtime.
*
* @parameter
*/
public Dependency[] shared;
/**
* Location of the local repository.
*
* @parameter expression="${localRepository}"
* @readonly
* @required
*/
public ArtifactRepository localRepository;
/**
* @parameter expression="${component.org.fabric3.runtime.maven.itest.ArtifactHelper}"
* @required
* @readonly
*/
public ArtifactHelper artifactHelper;
/**
* @parameter expression="${component.org.fabric3.runtime.maven.itest.ExtensionHelper}"
* @required
* @readonly
*/
public ExtensionHelper extensionHelper;
/**
* The sub-directory of the project's output directory which contains the systemConfig.xml file. Users are limited to specifying the (relative)
* directory name in this param - the file name is fixed. The fixed name is not required by the itest environment but using it retains the
* relationship between the test config file and WEB-INF/systemConfig.xml which contains the same information for the deployed composite
*
* @parameter
*/
public String systemConfigDir;
/**
* Allows the optional in-line specification of system configuration in the plugin configuration.
*
* @parameter
*/
public String systemConfig;
/**
* Build output directory.
*
* @parameter expression="${project.build.directory}"
* @required
*/
protected File outputDirectory;
/**
* Allows the optional in-line specification of an expected error
*
* @parameter
*/
public String errorText;
/**
* If false, external default repositories for transitive dependencies will not be used
*
* @parameter
*/
public boolean useDefaultRepositories = true;
/**
* JDK and system classpath packages to hide from the runtime classpath.
*
* @parameter
*/
public String[] hiddenPackages = HiddenPackages.getPackages();
/**
* @component
*/
public RuntimeInformation runtimeInformation;
public void execute() throws MojoExecutionException, MojoFailureException {
if (skip) {
getLog().info("Skipping integration tests by user request.");
return;
}
artifactHelper.setLocalRepository(localRepository);
artifactHelper.setProject(project);
MavenBootConfiguration configuration = createBootConfiguration();
Thread.currentThread().setContextClassLoader(configuration.getBootClassLoader());
MavenRuntimeBooter booter = new MavenRuntimeBooter(configuration);
MavenRuntime runtime = booter.boot();
try {
// load the contributions
deployContributions(runtime);
TestDeployer deployer = new TestDeployer(compositeNamespace, compositeName, buildDirectory, getLog());
boolean continueDeployment = deployer.deploy(runtime, errorText);
if (!continueDeployment) {
return;
}
TestRunner runner = new TestRunner(reportsDirectory, trimStackTrace, getLog());
runner.executeTests(runtime);
} catch (RuntimeException e) {
// log unexpected errors since Maven sometimes swallows them
getLog().error(e);
throw e;
} finally {
try {
tryLatch(runtime);
booter.shutdown();
} catch (Exception e) {
// ignore
}
}
}
/**
* Waits on a latch component if one is configured for the test run.
*
* @param runtime the runtime
*/
private void tryLatch(MavenRuntime runtime) {
Object latchComponent = runtime.getComponent(Object.class, TestConstants.TEST_LATCH_SERVICE);
if (latchComponent != null) {
Class> type = latchComponent.getClass();
try {
Method method = type.getDeclaredMethod("await");
getLog().info("Waiting on Fabric3 runtime latch");
method.invoke(latchComponent);
getLog().info("Fabric3 runtime latch released");
} catch (NoSuchMethodException e) {
getLog().error("Found latch service " + type + " but it does not declare an await() method");
} catch (SecurityException e) {
getLog().error("Security exception introspecting latch service", e);
} catch (IllegalAccessException e) {
getLog().error("Exception attempting to wait on latch service", e);
} catch (IllegalArgumentException e) {
getLog().error("Exception attempting to wait on latch service", e);
} catch (InvocationTargetException e) {
getLog().error("Exception attempting to wait on latch service", e);
}
}
}
/**
* Resolves and deploys configured contributions.
*
* @param runtime the runtime
* @throws MojoExecutionException if a deployment error occurs
*/
private void deployContributions(MavenRuntime runtime) throws MojoExecutionException {
if (contributions.length <= 0) {
return;
}
try {
ContributionService contributionService = runtime.getComponent(ContributionService.class, Names.CONTRIBUTION_SERVICE_URI);
Domain domain = runtime.getComponent(Domain.class, Names.APPLICATION_DOMAIN_URI);
List sources = new ArrayList();
for (Dependency contribution : contributions) {
Artifact artifact = artifactHelper.resolve(contribution, Collections.emptySet());
URL url = artifact.getFile().toURI().toURL();
URI uri = URI.create(new File(url.getFile()).getName());
ContributionSource source = new FileContributionSource(uri, url, -1, true);
sources.add(source);
}
List uris = contributionService.store(sources);
contributionService.install(uris);
domain.include(uris);
} catch (MalformedURLException e) {
throw new MojoExecutionException("Error installing contributions", e);
} catch (StoreException e) {
throw new MojoExecutionException("Error installing contributions", e);
} catch (DeploymentException e) {
throw new MojoExecutionException("Error installing contributions", e);
} catch (ContributionNotFoundException e) {
throw new MojoExecutionException("Error installing contributions", e);
} catch (InstallException e) {
throw new MojoExecutionException("Error installing contributions", e);
}
}
/**
* Recursively cleans the F3 temporary directory.
*/
private static void clearTempFiles() {
File f3TempDir = new File(System.getProperty("java.io.tmpdir"), ".f3");
try {
FileHelper.deleteDirectory(f3TempDir);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Creates the configuration to boot the Maven runtime, including resolving dependencies.
*
* @return the boot configuration
* @throws MojoExecutionException if there is an error creating the configuration
*/
private MavenBootConfiguration createBootConfiguration() throws MojoExecutionException {
int mavenVersion = runtimeInformation.getApplicationVersion().getMajorVersion();
Set runtimeArtifacts = artifactHelper.calculateRuntimeArtifacts(runtimeVersion, mavenVersion);
Set hostArtifacts = artifactHelper.calculateHostArtifacts(runtimeArtifacts, shared);
Set dependencies = artifactHelper.calculateDependencies();
Set moduleDependencies = artifactHelper.calculateModuleDependencies(dependencies, hostArtifacts);
Set expandedExtensions = new HashSet();
expandedExtensions.addAll(getCoreExtensions());
expandedExtensions.addAll(Arrays.asList(extensions));
ExpandedProfiles expandedProfiles = artifactHelper.expandProfileExtensions(profiles);
expandedExtensions.addAll(expandedProfiles.getExtensions());
ClassLoader parentClassLoader = getClass().getClassLoader();
if (hiddenPackages.length > 0) {
// mask hidden JDK and system classpath packages
parentClassLoader = new MaskingClassLoader(parentClassLoader, hiddenPackages);
}
ClassLoader hostClassLoader = createHostClassLoader(parentClassLoader, hostArtifacts);
ClassLoader bootClassLoader = createBootClassLoader(hostClassLoader, runtimeArtifacts);
MavenBootConfiguration configuration = new MavenBootConfiguration();
configuration.setMavenVersion(mavenVersion);
configuration.setBootClassLoader(bootClassLoader);
configuration.setHostClassLoader(hostClassLoader);
configuration.setLog(getLog());
configuration.setExtensionHelper(extensionHelper);
configuration.setExtensions(expandedExtensions);
if (useDefaultRepositories) {
configuration.setRemoteRepositories(expandedProfiles.getRepositories());
}
configuration.setModuleDependencies(moduleDependencies);
configuration.setOutputDirectory(outputDirectory);
configuration.setSystemConfig(systemConfig);
configuration.setSystemConfigDir(systemConfigDir);
return configuration;
}
/**
* Creates the classloader to boot the runtime.
*
* @param parent the parent classloader
* @param artifacts the set of artifacts to include on the boot classpath
* @return the boot classloader
*/
private ClassLoader createBootClassLoader(ClassLoader parent, Set artifacts) {
URL[] urls = new URL[artifacts.size()];
int i = 0;
for (Artifact artifact : artifacts) {
File file = artifact.getFile();
assert file != null;
try {
urls[i++] = file.toURI().toURL();
} catch (MalformedURLException e) {
// toURI should have made this valid
throw new AssertionError(e);
}
}
Log log = getLog();
if (log.isDebugEnabled()) {
log.debug("Fabric3 boot classpath:");
for (URL url : urls) {
log.debug(" " + url);
}
}
return new DelegatingResourceClassLoader(urls, parent);
}
/**
* Creates the host classloader based on the given set of artifacts.
*
* @param parent the parent classloader
* @param hostArtifacts the artifacts
* @return the host classloader
*/
private ClassLoader createHostClassLoader(ClassLoader parent, Set hostArtifacts) {
List urls = new ArrayList(hostArtifacts.size());
for (Artifact artifact : hostArtifacts) {
try {
File pathElement = artifact.getFile();
URL url = pathElement.toURI().toURL();
getLog().debug("Adding artifact URL: " + url);
urls.add(url);
} catch (MalformedURLException e) {
// toURI should have encoded the URL
throw new AssertionError(e);
}
}
return new DelegatingResourceClassLoader(urls.toArray(new URL[urls.size()]), parent);
}
/**
* Returns the core runtime extensions as a set of dependencies
*
* @return the extensions
*/
private Set getCoreExtensions() {
Set extensions = new HashSet();
Dependency dependency = new Dependency();
dependency.setGroupId("org.codehaus.fabric3");
dependency.setArtifactId("fabric3-jdk-proxy");
dependency.setVersion(runtimeVersion);
dependency.setType("jar");
extensions.add(dependency);
dependency = new Dependency();
dependency.setGroupId("org.codehaus.fabric3");
dependency.setArtifactId("fabric3-java");
dependency.setVersion(runtimeVersion);
dependency.setType("jar");
extensions.add(dependency);
dependency = new Dependency();
dependency.setGroupId("org.codehaus.fabric3");
dependency.setArtifactId("fabric3-async");
dependency.setVersion(runtimeVersion);
dependency.setType("jar");
extensions.add(dependency);
dependency = new Dependency();
dependency.setGroupId("org.codehaus.fabric3");
dependency.setArtifactId("fabric3-sca-intents");
dependency.setVersion(runtimeVersion);
dependency.setType("jar");
extensions.add(dependency);
dependency = new Dependency();
dependency.setGroupId("org.codehaus.fabric3");
dependency.setArtifactId("fabric3-resource");
dependency.setVersion(runtimeVersion);
dependency.setType("jar");
extensions.add(dependency);
dependency = new Dependency();
dependency.setGroupId("org.codehaus.fabric3");
dependency.setArtifactId("fabric3-execution");
dependency.setVersion(runtimeVersion);
dependency.setType("jar");
extensions.add(dependency);
dependency = new Dependency();
dependency.setGroupId("org.codehaus.fabric3");
dependency.setArtifactId("fabric3-maven-extension");
dependency.setVersion(runtimeVersion);
dependency.setType("jar");
extensions.add(dependency);
dependency = new Dependency();
dependency.setGroupId("org.codehaus.fabric3");
dependency.setArtifactId("fabric3-junit");
dependency.setVersion(runtimeVersion);
dependency.setType("jar");
extensions.add(dependency);
return extensions;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy