[KARAF-4553] Allow karaf boot starters to define maven plugins to call
diff --git a/samples/blueprint/service-provider/pom.xml b/samples/blueprint/service-provider/pom.xml
index 08b0912..3f0cbf2 100644
--- a/samples/blueprint/service-provider/pom.xml
+++ b/samples/blueprint/service-provider/pom.xml
@@ -18,6 +18,9 @@
<groupId>org.apache.karaf.boot</groupId>
<artifactId>karaf-boot-sample-service-provider-blueprint</artifactId>
<version>1.0.0-SNAPSHOT</version>
+ <properties>
+ <scanPath>sample</scanPath>
+ </properties>
<dependencies>
<dependency>
@@ -36,24 +39,6 @@
<extensions>true</extensions>
</plugin>
<plugin>
- <groupId>org.apache.aries.blueprint</groupId>
- <artifactId>blueprint-maven-plugin</artifactId>
- <version>1.3.0</version>
- <executions>
- <execution>
- <goals>
- <goal>blueprint-generate</goal>
- </goals>
- <phase>process-classes</phase>
- </execution>
- </executions>
- <configuration>
- <scanPaths>
- <scanPath>sample</scanPath>
- </scanPaths>
- </configuration>
- </plugin>
- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
diff --git a/starters/karaf-boot-starter-blueprint/src/main/resources/karaf-boot/plugins.xml b/starters/karaf-boot-starter-blueprint/src/main/resources/karaf-boot/plugins.xml
new file mode 100644
index 0000000..75a2f8a
--- /dev/null
+++ b/starters/karaf-boot-starter-blueprint/src/main/resources/karaf-boot/plugins.xml
@@ -0,0 +1,19 @@
+<plugin>
+ <groupId>org.apache.aries.blueprint</groupId>
+ <artifactId>blueprint-maven-plugin</artifactId>
+ <version>1.5.0-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>blueprint-generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <project>${project}</project>
+ <generatedFileName>autowire.xml</generatedFileName>
+ <scanPaths>
+ <scanPath>${scanPath}</scanPath>
+ </scanPaths>
+ </configuration>
+</plugin>
diff --git a/tools/karaf-boot-maven-plugin/pom.xml b/tools/karaf-boot-maven-plugin/pom.xml
index 89b3a5c..bed2067 100644
--- a/tools/karaf-boot-maven-plugin/pom.xml
+++ b/tools/karaf-boot-maven-plugin/pom.xml
@@ -67,6 +67,13 @@
<artifactId>plexus-build-api</artifactId>
<version>0.0.7</version>
</dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java b/tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java
index b6573f5..64a63f6 100644
--- a/tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java
+++ b/tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java
@@ -11,6 +11,7 @@
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -23,12 +24,8 @@
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.BuildPluginManager;
-import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.PluginDescriptorParsingException;
-import org.apache.maven.plugin.PluginNotFoundException;
-import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugins.annotations.Component;
@@ -38,24 +35,13 @@
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.xbean.finder.ClassFinder;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.sonatype.plexus.build.incremental.BuildContext;
@Mojo(name = "generate", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, inheritByDefault = false)
public class GenerateMojo extends AbstractMojo {
- private final class BuildStreamFactory implements StreamFactory {
- @Override
- public OutputStream create(File file) {
- try {
- file.getParentFile().mkdirs();
- return buildContext.newFileOutputStream(file);
- } catch (IOException e) {
- throw new RuntimeException("Error creating file " + file, e);
- }
- }
- }
-
@Parameter(defaultValue = "${project}", required = true, readonly = true)
private MavenProject mavenProject;
@@ -74,51 +60,97 @@
public void execute() throws MojoExecutionException {
try {
File buildDir = new File(project.getBuild().getDirectory());
- File generatedDir = new File(buildDir, "generated-resources");
- Resource resource = new Resource();
- resource.setDirectory(generatedDir.getPath());
- project.addResource(resource);
- ClassFinder finder = createProjectScopeFinder();
- List<Class<? extends BootPlugin>> plugins = finder.findImplementations(BootPlugin.class);
- Map<String, List<String>> combined = new HashMap<String, List<String>>();
- for (Class<? extends BootPlugin> pluginClass : plugins) {
- BootPlugin plugin = pluginClass.newInstance();
- Class<? extends Annotation> annotation = plugin.getAnnotation();
- List<Class<?>> classes = finder.findAnnotatedClasses(annotation);
- if (!classes.isEmpty()) {
- Map<String, List<String>> headers = plugin.enhance(classes, generatedDir, new BuildStreamFactory());
- combine(combined, headers);
- }
- }
- Map<String, List<String>> headers = new HashMap<String, List<String>>();
- headers.put("Import-Package", Arrays.asList("*"));
- combine(combined, headers);
- File bndInst = new File(buildDir, "org.apache.karaf.boot.bnd");
- writeBndFile(bndInst, combined);
+ File generatedDir = createGeneratedDir(buildDir);
+
+ URLClassLoader loader = projectClassLoader();
+ handleBootPlugins(loader, buildDir, generatedDir);
+ handleMavenPlugins(loader);
- InputStream is = this.getClass().getResourceAsStream("/configuration.xml");
- MojoExecution execution = new MojoExecution(getBundleMojo(), Xpp3DomBuilder.build(is, "utf-8"));
- pluginManager.executeMojo(mavenSession, execution);
+ runMavenBundlePlugin();
} catch (Exception e) {
throw new MojoExecutionException("karaf-boot-maven-plugin failed", e);
}
}
- private MojoDescriptor getBundleMojo() throws PluginNotFoundException, PluginResolutionException,
- PluginDescriptorParsingException, InvalidPluginDescriptorException {
- getLog().info("Invoking maven-bundle-plugin");
- Plugin felixBundlePlugin = new Plugin();
- felixBundlePlugin.setGroupId("org.apache.felix");
- felixBundlePlugin.setArtifactId("maven-bundle-plugin");
- felixBundlePlugin.setVersion("3.0.0");
- felixBundlePlugin.setInherited(true);
- felixBundlePlugin.setExtensions(true);
- PluginDescriptor felixBundlePluginDescriptor = pluginManager.loadPlugin(felixBundlePlugin, mavenProject.getRemotePluginRepositories(), mavenSession.getRepositorySession());
- MojoDescriptor felixBundleMojoDescriptor = felixBundlePluginDescriptor.getMojo("bundle");
- return felixBundleMojoDescriptor;
+ private void handleMavenPlugins(URLClassLoader loader) throws Exception {
+ Enumeration<URL> resources = loader.getResources("karaf-boot/plugins.xml");
+ while (resources.hasMoreElements()) {
+ URL res = resources.nextElement();
+ executePluginDef(res.openStream());
+ }
}
+ private void executePluginDef(InputStream is) throws Exception {
+ Xpp3Dom pluginDef = Xpp3DomBuilder.build(is, "utf-8");
+ Plugin plugin = loadPlugin(pluginDef);
+ Xpp3Dom config = pluginDef.getChild("configuration");
+ PluginDescriptor pluginDesc = pluginManager.loadPlugin(plugin,
+ mavenProject.getRemotePluginRepositories(),
+ mavenSession.getRepositorySession());
+ Xpp3Dom executions = pluginDef.getChild("executions");
+
+ for ( Xpp3Dom execution : executions.getChildren()) {
+ Xpp3Dom goals = execution.getChild("goals");
+ for (Xpp3Dom goal : goals.getChildren()) {
+ MojoDescriptor desc = pluginDesc.getMojo(goal.getValue());
+ pluginManager.executeMojo(mavenSession, new MojoExecution(desc, config));
+ }
+ }
+ }
+
+ Plugin loadPlugin(Xpp3Dom pluginDef) {
+ String groupId = pluginDef.getChild("groupId").getValue();
+ String artifactId = pluginDef.getChild("artifactId").getValue();
+ String version = pluginDef.getChild("version").getValue();
+ Plugin plugin = new Plugin();
+ plugin.setGroupId(groupId);
+ plugin.setArtifactId(artifactId);
+ plugin.setVersion(version);
+ return plugin;
+ }
+
+ private File createGeneratedDir(File buildDir) {
+ File generatedDir = new File(buildDir, "generated-resources");
+ Resource resource = new Resource();
+ resource.setDirectory(generatedDir.getPath());
+ project.addResource(resource);
+ return generatedDir;
+ }
+
+ private void handleBootPlugins(URLClassLoader loader, File buildDir, File generatedDir)
+ throws MalformedURLException, InstantiationException, IllegalAccessException, IOException {
+ ClassFinder finder = new ClassFinder(loader, Arrays.asList(loader.getURLs()));
+ List<Class<? extends BootPlugin>> plugins = finder.findImplementations(BootPlugin.class);
+ Map<String, List<String>> headers = new HashMap<String, List<String>>();
+ for (Class<? extends BootPlugin> pluginClass : plugins) {
+ applyBootPlugin(generatedDir, finder, headers, pluginClass);
+ }
+ addImportDefault(headers);
+ File bndInst = new File(buildDir, "org.apache.karaf.boot.bnd");
+ writeBndFile(bndInst, headers);
+ }
+
+ private void applyBootPlugin(File generatedDir, ClassFinder finder, Map<String, List<String>> combined,
+ Class<? extends BootPlugin> pluginClass)
+ throws InstantiationException, IllegalAccessException {
+ BootPlugin plugin = pluginClass.newInstance();
+ Class<? extends Annotation> annotation = plugin.getAnnotation();
+ List<Class<?>> classes = finder.findAnnotatedClasses(annotation);
+ if (!classes.isEmpty()) {
+ Map<String, List<String>> headers = plugin.enhance(classes, generatedDir, new BuildStreamFactory());
+ combine(combined, headers);
+ }
+ }
+
+ private void addImportDefault(Map<String, List<String>> combined) {
+ Map<String, List<String>> headers = new HashMap<String, List<String>>();
+ headers.put("Import-Package", Arrays.asList("*"));
+ combine(combined, headers);
+ }
+
+
+
private void writeBndFile(File bndInst, Map<String, List<String>> combined) throws IOException {
try (
OutputStream os = buildContext.newFileOutputStream(bndInst);
@@ -142,19 +174,47 @@
}
}
- private ClassFinder createProjectScopeFinder() throws MalformedURLException {
+ private URLClassLoader projectClassLoader() throws MalformedURLException {
List<URL> urls = new ArrayList<URL>();
-
urls.add(new File(project.getBuild().getOutputDirectory()).toURI().toURL());
- for (Object artifactO : project.getArtifacts()) {
- Artifact artifact = (Artifact) artifactO;
+ for (Artifact artifact : project.getArtifacts()) {
File file = artifact.getFile();
if (file != null) {
urls.add(file.toURI().toURL());
}
}
- ClassLoader loader = new URLClassLoader(urls.toArray(new URL[urls.size()]), getClass().getClassLoader());
- return new ClassFinder(loader, urls);
+ URLClassLoader loader = new URLClassLoader(urls.toArray(new URL[urls.size()]), getClass().getClassLoader());
+ return loader;
}
+ private void runMavenBundlePlugin() throws Exception {
+ InputStream is = this.getClass().getResourceAsStream("/configuration.xml");
+ MojoExecution execution = new MojoExecution(getMavenBundleMojo(), Xpp3DomBuilder.build(is, "utf-8"));
+ getLog().info("Invoking maven-bundle-plugin");
+ pluginManager.executeMojo(mavenSession, execution);
+ }
+
+ private MojoDescriptor getMavenBundleMojo() throws Exception {
+ Plugin plugin = new Plugin();
+ plugin.setGroupId("org.apache.felix");
+ plugin.setArtifactId("maven-bundle-plugin");
+ plugin.setVersion("3.0.0");
+ plugin.setInherited(true);
+ plugin.setExtensions(true);
+ PluginDescriptor desc = pluginManager.loadPlugin(plugin, mavenProject.getRemotePluginRepositories(), mavenSession.getRepositorySession());
+ return desc.getMojo("bundle");
+ }
+
+
+ private final class BuildStreamFactory implements StreamFactory {
+ @Override
+ public OutputStream create(File file) {
+ try {
+ file.getParentFile().mkdirs();
+ return buildContext.newFileOutputStream(file);
+ } catch (IOException e) {
+ throw new RuntimeException("Error creating file " + file, e);
+ }
+ }
+ }
}
diff --git a/tools/karaf-boot-maven-plugin/src/test/java/org/apache/karaf/boot/maven/PluginLoaderTest.java b/tools/karaf-boot-maven-plugin/src/test/java/org/apache/karaf/boot/maven/PluginLoaderTest.java
new file mode 100644
index 0000000..ab362d0
--- /dev/null
+++ b/tools/karaf-boot-maven-plugin/src/test/java/org/apache/karaf/boot/maven/PluginLoaderTest.java
@@ -0,0 +1,25 @@
+package org.apache.karaf.boot.maven;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.maven.model.Plugin;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PluginLoaderTest {
+
+ @Test
+ public void testLoadXml() throws XmlPullParserException, IOException {
+ InputStream is = this.getClass().getResourceAsStream("/plugins.xml");
+ Xpp3Dom pluginDef = Xpp3DomBuilder.build(is, "utf-8");
+ Plugin plugin = new GenerateMojo().loadPlugin(pluginDef);
+ Assert.assertEquals("org.apache.aries.blueprint", plugin.getGroupId());
+ Assert.assertEquals("blueprint-maven-plugin", plugin.getArtifactId());
+ Assert.assertEquals("1.4.0", plugin.getVersion());
+ }
+
+}
diff --git a/tools/karaf-boot-maven-plugin/src/test/resources/plugins.xml b/tools/karaf-boot-maven-plugin/src/test/resources/plugins.xml
new file mode 100644
index 0000000..b03a2f2
--- /dev/null
+++ b/tools/karaf-boot-maven-plugin/src/test/resources/plugins.xml
@@ -0,0 +1,17 @@
+<plugin>
+ <groupId>org.apache.aries.blueprint</groupId>
+ <artifactId>blueprint-maven-plugin</artifactId>
+ <version>1.4.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>blueprint-generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <scanPaths>
+ <scanPath>${scanPath}</scanPath>
+ </scanPaths>
+ </configuration>
+</plugin>