blob: 86e5251ef61660a44427d22af9acd08dd3b0c720 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.servicemix.maven.plugin.jbi;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactCollector;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.servicemix.maven.plugin.jbi.JbiResolutionListener.Node;
import org.codehaus.plexus.archiver.jar.Manifest;
import org.codehaus.plexus.archiver.jar.ManifestException;
import org.codehaus.plexus.util.xml.Xpp3Dom;
public abstract class AbstractJbiMojo extends AbstractMojo {
public static final String META_INF = "META-INF";
public static final String JBI_DESCRIPTOR = "jbi.xml";
public static final String LIB_DIRECTORY = "lib";
private static final Pattern VERSION_PATTERN = Pattern.compile("^(\\d+(\\.\\d+(\\.\\d+)?)?)-");
private static final String[] VERSION_COMPLETERS = new String[] {".0.0", ".0" };
/**
* Maven ProjectHelper
*
* @component
*/
protected MavenProjectHelper projectHelper;
/**
* The maven project.
*
* @parameter expression="${project}"
* @required
* @readonly
*/
protected MavenProject project;
/**
* Directory that resources are copied to during the build.
*
* @parameter expression="${project.build.directory}/${project.artifactId}-${project.version}-installer"
* @required
*/
protected File workDirectory;
/**
* @component
*/
protected MavenProjectBuilder projectBuilder;
/**
* @parameter default-value="${localRepository}"
*/
protected ArtifactRepository localRepo;
/**
* @parameter default-value="${project.remoteArtifactRepositories}"
*/
protected List remoteRepos;
/**
* @component
*/
protected ArtifactMetadataSource artifactMetadataSource;
/**
* @component
*/
protected ArtifactResolver resolver;
/**
* @component
* @required
* @readonly
*/
protected ArtifactCollector collector;
/**
* @component
*/
protected ArtifactFactory factory;
protected MavenProject getProject() {
return project;
}
protected File getWorkDirectory() {
return workDirectory;
}
public MavenProjectHelper getProjectHelper() {
return projectHelper;
}
protected void removeBranch(JbiResolutionListener listener, Artifact artifact) {
Node n = listener.getNode(artifact);
if (n != null) {
for (Node parent : n.getParents()) {
parent.getChildren().remove(n);
}
}
}
protected void removeChildren(JbiResolutionListener listener, Artifact artifact) {
Node n = listener.getNode(artifact);
n.getChildren().clear();
}
protected Set<Artifact> getArtifacts(Node n, Set<Artifact> s) {
if (s.add(n.getArtifact())) {
for (Node c : n.getChildren()) {
getArtifacts(c, s);
}
}
return s;
}
protected void excludeBranch(Node n, Set<Artifact> excludes) {
excludes.add(n.getArtifact());
for (Node c : n.getChildren()) {
excludeBranch(c, excludes);
}
}
protected void print(Node rootNode) {
for (Artifact a : getArtifacts(rootNode, new HashSet<Artifact>())) {
getLog().info(" " + a);
}
}
protected void print(Node rootNode, String pfx) {
getLog().info(pfx + rootNode.getArtifact());
for (Node child : rootNode.getChildren()) {
print(child, " " + pfx);
}
}
protected void pruneTree(Node node, Set<Artifact> excludes) {
for (Iterator<Node> iter = node.getChildren().iterator(); iter.hasNext();) {
Node child = iter.next();
if (child.getArtifact().isOptional() ||
(!child.getScope().equals(Artifact.SCOPE_COMPILE) && !child.getScope().equals(Artifact.SCOPE_RUNTIME)) ||
excludes.contains(child.getArtifact())) {
iter.remove();
} else {
pruneTree(child, excludes);
}
}
}
protected Set<Artifact> retainArtifacts(Set<Artifact> includes, JbiResolutionListener listener) {
Set<Artifact> finalIncludes = new HashSet<Artifact>();
Set<Artifact> filteredArtifacts = getArtifacts(listener.getRootNode(), new HashSet<Artifact>());
for (Artifact artifact : includes) {
for (Artifact filteredArtifact : filteredArtifacts) {
if (filteredArtifact.getArtifactId().equals(
artifact.getArtifactId())
&& filteredArtifact.getType()
.equals(artifact.getType())
&& filteredArtifact.getGroupId().equals(
artifact.getGroupId())) {
if (!filteredArtifact.getVersion().equals(
artifact.getVersion())) {
getLog()
.warn(
"Resolved artifact "
+ artifact
+ " has a different version from that in dependency management "
+ filteredArtifact
+ ", overriding dependency management");
}
finalIncludes.add(artifact);
}
}
}
return finalIncludes;
}
protected JbiResolutionListener resolveProject() {
Map managedVersions = null;
try {
managedVersions = createManagedVersionMap(project.getId(), project.getDependencyManagement());
} catch (ProjectBuildingException e) {
getLog().error("An error occurred while resolving project dependencies.", e);
}
JbiResolutionListener listener = new JbiResolutionListener();
listener.setLog(getLog());
try {
collector.collect(project.getDependencyArtifacts(), project
.getArtifact(), managedVersions, localRepo, remoteRepos,
artifactMetadataSource, null, Collections
.singletonList(listener));
} catch (ArtifactResolutionException e) {
getLog().error(
"An error occurred while resolving project dependencies.",
e);
}
if (getLog().isDebugEnabled()) {
getLog().debug("Dependency graph");
getLog().debug("================");
print(listener.getRootNode());
getLog().debug("================");
}
return listener;
}
protected Map createManagedVersionMap(String projectId,
DependencyManagement dependencyManagement) throws ProjectBuildingException {
Map map;
if (dependencyManagement != null
&& dependencyManagement.getDependencies() != null) {
map = new HashMap();
for (Iterator i = dependencyManagement.getDependencies().iterator(); i
.hasNext();) {
Dependency d = (Dependency) i.next();
try {
VersionRange versionRange = VersionRange
.createFromVersionSpec(d.getVersion());
Artifact artifact = factory.createDependencyArtifact(d
.getGroupId(), d.getArtifactId(), versionRange, d
.getType(), d.getClassifier(), d.getScope());
map.put(d.getManagementKey(), artifact);
} catch (InvalidVersionSpecificationException e) {
throw new ProjectBuildingException(projectId,
"Unable to parse version '" + d.getVersion()
+ "' for dependency '"
+ d.getManagementKey() + "': "
+ e.getMessage(), e);
}
}
} else {
map = Collections.EMPTY_MAP;
}
return map;
}
/**
* Set up a classloader for the execution of the main class.
*
* @return
* @throws MojoExecutionException
*/
protected URLClassLoader getClassLoader() throws MojoExecutionException {
try {
Set urls = new HashSet();
URL mainClasses = new File(project.getBuild().getOutputDirectory())
.toURL();
getLog().debug("Adding to classpath : " + mainClasses);
urls.add(mainClasses);
URL testClasses = new File(project.getBuild()
.getTestOutputDirectory()).toURL();
getLog().debug("Adding to classpath : " + testClasses);
urls.add(testClasses);
Set dependencies = project.getArtifacts();
Iterator iter = dependencies.iterator();
while (iter.hasNext()) {
Artifact classPathElement = (Artifact) iter.next();
getLog().debug(
"Adding artifact: " + classPathElement.getFile()
+ " to classpath");
urls.add(classPathElement.getFile().toURL());
}
URLClassLoader appClassloader = new URLClassLoader((URL[]) urls
.toArray(new URL[urls.size()]), this.getClass().getClassLoader());
return appClassloader;
} catch (MalformedURLException e) {
throw new MojoExecutionException(
"Error during setting up classpath", e);
}
}
protected Manifest createManifest() throws ManifestException {
Manifest manifest = new Manifest();
//manifest.getMainSection().addConfiguredAttribute(new Manifest.Attribute("Bundle-Name", project.getName()));
//manifest.getMainSection().addConfiguredAttribute(new Manifest.Attribute("Bundle-SymbolicName", project.getArtifactId()));
//manifest.getMainSection().addConfiguredAttribute(new Manifest.Attribute(
//"Bundle-Version", fixBundleVersion(project.getVersion())));
return manifest;
}
public static String fixBundleVersion(String version) {
// Maven uses a '-' to separate the version qualifier, while
// OSGi uses a '.', so we need to convert the first '-' to a
// '.' and fill in any missing minor or micro version
// components if necessary.
final Matcher matcher = VERSION_PATTERN.matcher(version);
if (!matcher.lookingAt()) {
return version;
}
// Leave extra space for worst-case additional insertion:
final StringBuffer sb = new StringBuffer(version.length() + 4);
sb.append(matcher.group(1));
if (null == matcher.group(3)) {
final int count = null != matcher.group(2) ? 2 : 1;
sb.append(VERSION_COMPLETERS[count - 1]);
}
sb.append('.');
sb.append(version.substring(matcher.end(), version.length()));
return sb.toString();
}
protected String getServiceUnitName(MavenProject project) {
for (Object elem : project.getBuildPlugins()) {
if (elem instanceof Plugin) {
Plugin plugin = (Plugin)elem;
if (plugin.getGroupId().equals("org.apache.servicemix.tooling")
&& plugin.getArtifactId().equals("jbi-maven-plugin")) {
Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration();
if (configuration != null) {
Xpp3Dom serviceUnitName = configuration.getChild("serviceUnitName");
if (serviceUnitName != null) {
return serviceUnitName.getValue();
}
}
break;
}
}
}
return null;
}
}