You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2016/05/09 14:48:39 UTC

[20/35] karaf-boot git commit: [karaf] fix karaf extensions

[karaf] fix karaf extensions

Project: http://git-wip-us.apache.org/repos/asf/karaf-boot/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf-boot/commit/9d68baae
Tree: http://git-wip-us.apache.org/repos/asf/karaf-boot/tree/9d68baae
Diff: http://git-wip-us.apache.org/repos/asf/karaf-boot/diff/9d68baae

Branch: refs/heads/master
Commit: 9d68baae7b1e36124fd70196e739aa393036d470
Parents: 1d2b774
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Apr 15 18:26:30 2016 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Apr 15 18:26:30 2016 +0200

----------------------------------------------------------------------
 .../pom.xml                                     |   2 +-
 .../pom.xml                                     |   2 +-
 .../karaf-boot-starter-karaf/pom.xml            |  57 +++++++
 .../karaf/boot/karaf/impl/KarafProcessor.java   | 154 +++++++++++++++++++
 .../javax.annotation.processing.Processor       |   1 +
 .../karaf-boot-starter-shell/pom.xml            |  11 ++
 .../karaf/boot/shell/impl/ShellProcessor.java   |  84 ++++++++++
 .../javax.annotation.processing.Processor       |   1 +
 karaf-boot-starters/karaf-boot-starter/pom.xml  |   5 -
 karaf-boot-starters/pom.xml                     |   1 +
 .../apache/karaf/boot/maven/GenerateMojo.java   | 114 ++++++--------
 11 files changed, 356 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-samples/karaf-boot-sample-service-consumer-osgi/pom.xml
----------------------------------------------------------------------
diff --git a/karaf-boot-samples/karaf-boot-sample-service-consumer-osgi/pom.xml b/karaf-boot-samples/karaf-boot-sample-service-consumer-osgi/pom.xml
index c26cfbf..2a18273 100644
--- a/karaf-boot-samples/karaf-boot-sample-service-consumer-osgi/pom.xml
+++ b/karaf-boot-samples/karaf-boot-sample-service-consumer-osgi/pom.xml
@@ -28,7 +28,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.karaf.boot</groupId>
-            <artifactId>karaf-boot-starter</artifactId>
+            <artifactId>karaf-boot-starter-karaf</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-samples/karaf-boot-sample-service-provider-osgi/pom.xml
----------------------------------------------------------------------
diff --git a/karaf-boot-samples/karaf-boot-sample-service-provider-osgi/pom.xml b/karaf-boot-samples/karaf-boot-sample-service-provider-osgi/pom.xml
index d1bb116..507828a 100644
--- a/karaf-boot-samples/karaf-boot-sample-service-provider-osgi/pom.xml
+++ b/karaf-boot-samples/karaf-boot-sample-service-provider-osgi/pom.xml
@@ -28,7 +28,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.karaf.boot</groupId>
-            <artifactId>karaf-boot-starter</artifactId>
+            <artifactId>karaf-boot-starter-karaf</artifactId>
             <version>${project.version}</version>
         </dependency>
     </dependencies>

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-starters/karaf-boot-starter-karaf/pom.xml
----------------------------------------------------------------------
diff --git a/karaf-boot-starters/karaf-boot-starter-karaf/pom.xml b/karaf-boot-starters/karaf-boot-starter-karaf/pom.xml
new file mode 100644
index 0000000..32bec48
--- /dev/null
+++ b/karaf-boot-starters/karaf-boot-starter-karaf/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.boot</groupId>
+        <artifactId>karaf-boot-starters</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>karaf-boot-starter-karaf</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>${osgi.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <version>${karaf.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <compilerArgument>-proc:none</compilerArgument>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-starters/karaf-boot-starter-karaf/src/main/java/org/apache/karaf/boot/karaf/impl/KarafProcessor.java
----------------------------------------------------------------------
diff --git a/karaf-boot-starters/karaf-boot-starter-karaf/src/main/java/org/apache/karaf/boot/karaf/impl/KarafProcessor.java b/karaf-boot-starters/karaf-boot-starter-karaf/src/main/java/org/apache/karaf/boot/karaf/impl/KarafProcessor.java
new file mode 100644
index 0000000..e51380e
--- /dev/null
+++ b/karaf-boot-starters/karaf-boot-starter-karaf/src/main/java/org/apache/karaf/boot/karaf/impl/KarafProcessor.java
@@ -0,0 +1,154 @@
+package org.apache.karaf.boot.karaf.impl;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.karaf.util.tracker.annotation.Managed;
+import org.apache.karaf.util.tracker.annotation.ProvideService;
+import org.apache.karaf.util.tracker.annotation.RequireService;
+import org.apache.karaf.util.tracker.annotation.Services;
+
+public class KarafProcessor extends AbstractProcessor {
+
+    boolean hasRun;
+
+    public KarafProcessor() {
+    }
+
+    @Override
+    public Set<String> getSupportedAnnotationTypes() {
+        Set<String> set = new HashSet<String>();
+        set.add(Services.class.getName());
+        set.add(Managed.class.getName());
+        return set;
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        List<String> instructions = new ArrayList<>();
+        Properties props = new Properties();
+
+        for (Element elem : roundEnv.getElementsAnnotatedWith(Services.class)) {
+            for (AnnotationMirror mirror : elem.getAnnotationMirrors()) {
+                if (Services.class.getName().equals(((TypeElement) mirror.getAnnotationType().asElement()).getQualifiedName().toString())) {
+                    Map<String, Object> values = getAnnotationValues(mirror);
+                    if (values.containsKey("provides")) {
+                        for (AnnotationMirror p : (List<AnnotationMirror>) values.get("provides")) {
+                            Map<String, Object> pv = getAnnotationValues(p);
+                            String n = pv.get("value").toString();
+                            instructions.add("Provide-Capability: osgi.service;effective:=active;objectClass=" + n);
+                        }
+                    }
+                    if (values.containsKey("requires")) {
+                        for (AnnotationMirror r : (List<AnnotationMirror>) values.get("requires")) {
+                            Map<String, Object> rv = getAnnotationValues(r);
+                            String value = rv.get("value").toString();
+                            String filter = (String) rv.getOrDefault("filter", "");
+                            boolean opt = ((Boolean) rv.getOrDefault("optional", false));
+
+                            String fltWithClass = combine(filter, "(objectClass=" + value + ")");
+                            instructions.add("Require-Capability: osgi.service;effective:=active;filter:=\"" + fltWithClass + "\"");
+                            props.setProperty(value, filter);
+                        }
+                    }
+                }
+            }
+            instructions.add("Bundle-Activator: " + ((TypeElement) elem).getQualifiedName().toString());
+
+            Managed managed = elem.getAnnotation(Managed.class);
+            if (managed != null) {
+                props.setProperty("pid", managed.value());
+            }
+
+            String name = "OSGI-INF/karaf-tracker/" + ((TypeElement) elem).getQualifiedName().toString();
+            try (OutputStream os = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", name).openOutputStream()) {
+                props.store(os, null);
+            } catch (IOException e) {
+                processingEnv.getMessager().printMessage(Kind.ERROR, "Error writing to " + name + ": " + e.getMessage());
+            }
+        }
+
+        instructions.add("Private-Package: org.apache.karaf.util.tracker");
+        instructions.add("PREPEND-Import-Package: !org.apache.karaf.util.tracker.annotation");
+
+        if (!hasRun) {
+            hasRun = true;
+            // Add the Karaf embedded package
+            try (PrintWriter w = appendResource("META-INF/org.apache.karaf.boot.bnd")) {
+                for (String instr : instructions) {
+                    w.println(instr);
+                }
+            } catch (Exception e) {
+                processingEnv.getMessager().printMessage(Kind.ERROR, "Error writing to META-INF/org.apache.karaf.boot.bnd: " + e.getMessage());
+            }
+        }
+
+        return true;
+    }
+
+    private Map<String, Object> getAnnotationValues(AnnotationMirror mirror) {
+        Map<String, Object> map = new HashMap<>();
+        for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : mirror.getElementValues().entrySet()) {
+            map.put(entry.getKey().getSimpleName().toString(), entry.getValue().getValue());
+        }
+        return map;
+    }
+
+    private String combine(String filter1, String filter2) {
+        if (filter1!=null && !filter1.isEmpty()) {
+            return "(&" + filter2 + filter1 + ")";
+        } else {
+            return filter2;
+        }
+    }
+
+    private PrintWriter appendResource(String resource) throws IOException {
+        try {
+            FileObject o = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", resource);
+            return new PrintWriter(o.openWriter());
+        } catch (Exception e) {
+            try {
+                FileObject o = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", resource);
+                CharArrayWriter baos = new CharArrayWriter();
+                try (Reader r = o.openReader(true)) {
+                    char[] buf = new char[4096];
+                    int l;
+                    while ((l = r.read(buf)) > 0) {
+                        baos.write(buf, 0, l);
+                    }
+                }
+                o.delete();
+                o = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", resource);
+                Writer w = o.openWriter();
+                w.write(baos.toCharArray());
+                return new PrintWriter(w);
+            } catch (Exception e2) {
+                e2.addSuppressed(e);
+                e2.printStackTrace();
+                throw e2;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-starters/karaf-boot-starter-karaf/src/main/resources/META-INF/services/javax.annotation.processing.Processor
----------------------------------------------------------------------
diff --git a/karaf-boot-starters/karaf-boot-starter-karaf/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/karaf-boot-starters/karaf-boot-starter-karaf/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000..c45090b
--- /dev/null
+++ b/karaf-boot-starters/karaf-boot-starter-karaf/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+org.apache.karaf.boot.karaf.impl.KarafProcessor

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-starters/karaf-boot-starter-shell/pom.xml
----------------------------------------------------------------------
diff --git a/karaf-boot-starters/karaf-boot-starter-shell/pom.xml b/karaf-boot-starters/karaf-boot-starter-shell/pom.xml
index 4c413a8..28523c7 100644
--- a/karaf-boot-starters/karaf-boot-starter-shell/pom.xml
+++ b/karaf-boot-starters/karaf-boot-starter-shell/pom.xml
@@ -38,4 +38,15 @@
         </dependency>
     </dependencies>
 
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <compilerArgument>-proc:none</compilerArgument>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-starters/karaf-boot-starter-shell/src/main/java/org/apache/karaf/boot/shell/impl/ShellProcessor.java
----------------------------------------------------------------------
diff --git a/karaf-boot-starters/karaf-boot-starter-shell/src/main/java/org/apache/karaf/boot/shell/impl/ShellProcessor.java b/karaf-boot-starters/karaf-boot-starter-shell/src/main/java/org/apache/karaf/boot/shell/impl/ShellProcessor.java
new file mode 100644
index 0000000..3de3bfb
--- /dev/null
+++ b/karaf-boot-starters/karaf-boot-starter-shell/src/main/java/org/apache/karaf/boot/shell/impl/ShellProcessor.java
@@ -0,0 +1,84 @@
+package org.apache.karaf.boot.shell.impl;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+public class ShellProcessor extends AbstractProcessor {
+
+    boolean hasRun;
+
+    public ShellProcessor() {
+    }
+
+    @Override
+    public Set<String> getSupportedAnnotationTypes() {
+        Set<String> set = new HashSet<String>();
+        set.add(Service.class.getName());
+        return set;
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        Set<String> packages = new TreeSet<>();
+        for (Element elem : roundEnv.getElementsAnnotatedWith(Service.class)) {
+            packages.add(elem.getEnclosingElement().toString());
+        }
+
+        if (!packages.isEmpty()) {
+            if (!hasRun) {
+                hasRun = true;
+                // Add the Karaf embedded package
+                try (PrintWriter w = appendResource("META-INF/org.apache.karaf.boot.bnd")) {
+                    w.println("Karaf-Commands: " + String.join(",", packages));
+                } catch (Exception e) {
+                    processingEnv.getMessager().printMessage(Kind.ERROR, "Error writing to META-INF/org.apache.karaf.boot.bnd: " + e.getMessage());
+                }
+            }
+        }
+
+        return true;
+    }
+
+    private PrintWriter appendResource(String resource) throws IOException {
+        try {
+            FileObject o = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", resource);
+            return new PrintWriter(o.openWriter());
+        } catch (Exception e) {
+            try {
+                FileObject o = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", resource);
+                CharArrayWriter baos = new CharArrayWriter();
+                try (Reader r = o.openReader(true)) {
+                    char[] buf = new char[4096];
+                    int l;
+                    while ((l = r.read(buf)) > 0) {
+                        baos.write(buf, 0, l);
+                    }
+                }
+                o.delete();
+                o = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", resource);
+                Writer w = o.openWriter();
+                w.write(baos.toCharArray());
+                return new PrintWriter(w);
+            } catch (Exception e2) {
+                e2.addSuppressed(e);
+                e2.printStackTrace();
+                throw e2;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-starters/karaf-boot-starter-shell/src/main/resources/META-INF/services/javax.annotation.processing.Processor
----------------------------------------------------------------------
diff --git a/karaf-boot-starters/karaf-boot-starter-shell/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/karaf-boot-starters/karaf-boot-starter-shell/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000..3ebe726
--- /dev/null
+++ b/karaf-boot-starters/karaf-boot-starter-shell/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+org.apache.karaf.boot.shell.impl.ShellProcessor

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-starters/karaf-boot-starter/pom.xml
----------------------------------------------------------------------
diff --git a/karaf-boot-starters/karaf-boot-starter/pom.xml b/karaf-boot-starters/karaf-boot-starter/pom.xml
index 21c0d07..e5b2742 100644
--- a/karaf-boot-starters/karaf-boot-starter/pom.xml
+++ b/karaf-boot-starters/karaf-boot-starter/pom.xml
@@ -36,11 +36,6 @@
             <artifactId>org.osgi.core</artifactId>
             <version>${osgi.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <version>${karaf.version}</version>
-        </dependency>
     </dependencies>
 
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-starters/pom.xml
----------------------------------------------------------------------
diff --git a/karaf-boot-starters/pom.xml b/karaf-boot-starters/pom.xml
index e50f6c2..127874e 100644
--- a/karaf-boot-starters/pom.xml
+++ b/karaf-boot-starters/pom.xml
@@ -33,6 +33,7 @@
 
     <modules>
         <module>karaf-boot-starter</module>
+        <module>karaf-boot-starter-karaf</module>
         <module>karaf-boot-starter-ds</module>
         <module>karaf-boot-starter-shell</module>
         <module>karaf-boot-starter-web</module>

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/9d68baae/karaf-boot-tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java
----------------------------------------------------------------------
diff --git a/karaf-boot-tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java b/karaf-boot-tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java
index d7fcdcb..dd88688 100644
--- a/karaf-boot-tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java
+++ b/karaf-boot-tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java
@@ -15,6 +15,7 @@ import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.IOException;
 import java.io.StringReader;
 import java.nio.file.Files;
 import java.util.LinkedHashMap;
@@ -35,86 +36,27 @@ public class GenerateMojo extends AbstractMojo {
 
     public void execute() throws MojoExecutionException {
         try {
-            // invoke Karaf services plugin
-            getLog().info("Invoking karaf-services-maven-plugin");
-            Plugin karafServicesPlugin = new Plugin();
-            karafServicesPlugin.setGroupId("org.apache.karaf.tooling");
-            karafServicesPlugin.setArtifactId("karaf-services-maven-plugin");
-            karafServicesPlugin.setVersion("4.0.1");
-            karafServicesPlugin.setInherited(false);
-            karafServicesPlugin.setExtensions(true);
-            Xpp3Dom configuration = Xpp3DomBuilder.build(new ByteArrayInputStream(("<configuration>" +
-                    "<project>${project}</project>" +
-                    "<activatorProperty>BNDExtension-Bundle-Activator</activatorProperty>" +
-                    "<requirementsProperty>BNDExtension-Require-Capability</requirementsProperty>" +
-                    "<capabilitiesProperty>BNDExtension-Provide-Capability</capabilitiesProperty>" +
-                    "<outputDirectory>${project.build.directory}/generated/karaf-tracker</outputDirectory>" +
-                    "<classLoader>project</classLoader>" +
-                    "</configuration>").getBytes()), "UTF-8");
-            PluginDescriptor karafServicesPluginDescriptor = pluginManager.loadPlugin(karafServicesPlugin, mavenProject.getRemotePluginRepositories(), mavenSession.getRepositorySession());
-            MojoDescriptor karafServicesMojoDescriptor = karafServicesPluginDescriptor.getMojo("service-metadata-generate");
-            MojoExecution execution = new MojoExecution(karafServicesMojoDescriptor, configuration);
-            pluginManager.executeMojo(mavenSession, execution);
-
-            // invoke Felix bundle plugin
-            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);
-
-
             //
-            // Bundle plugin
+            // Felix Bundle plugin
             //
 
             Map<String, String> instructions = new LinkedHashMap<>();
-            instructions.put("Private-Package", "org.apache.karaf.util.tracker");
-            instructions.put("_dsannotations", "*");
-
-            //
             // Starters supplied instructions
-            //
             File bndInst = new File(mavenProject.getBasedir(), "target/classes/META-INF/org.apache.karaf.boot.bnd");
             if (bndInst.isFile()) {
-                List<String> lines =  Files.readAllLines(bndInst.toPath());
-                for (String line : lines) {
-                    if (!line.contains(":")) {
-                        continue;
-                    }
-                    String name = line.substring(0, line.indexOf(':')).trim();
-                    String value = line.substring(line.indexOf(':') + 1).trim();
-                    if (instructions.containsKey(name)) {
-                        instructions.put(name, instructions.get(name) + "," + value);
-                    } else {
-                        instructions.put(name, value);
-                    }
-                }
+                complete(instructions, bndInst);
                 bndInst.delete();
             }
-
-            //
             // User supplied instructions
-            //
             bndInst = new File(mavenProject.getBasedir(), "osgi.bnd");
             if (bndInst.isFile()) {
-                List<String> lines =  Files.readAllLines(bndInst.toPath());
-                for (String line : lines) {
-                    if (!line.contains(":")) {
-                        continue;
-                    }
-                    String name = line.substring(0, line.indexOf(':')).trim();
-                    String value = line.substring(line.indexOf(':') + 1).trim();
-                    if (instructions.containsKey(name)) {
-                        instructions.put(name, instructions.get(name) + "," + value);
-                    } else {
-                        instructions.put(name, value);
-                    }
-                }
+                complete(instructions, bndInst);
             }
-
+            // Verify and use defaults
+            if (instructions.containsKey("Import-Package")) {
+                instructions.put("Import-Package", instructions.get("Import-Package") + ",*");
+            }
+            // Build config
             StringBuilder config = new StringBuilder();
             config.append("<configuration>" +
                     "<finalName>${project.build.finalName}</finalName>" +
@@ -135,14 +77,48 @@ public class GenerateMojo extends AbstractMojo {
             }
             config.append("</instructions>" +
                     "</configuration>");
-            configuration = Xpp3DomBuilder.build(new StringReader(config.toString()));
+            Xpp3Dom configuration = Xpp3DomBuilder.build(new StringReader(config.toString()));
+            // Invoke plugin
+            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");
-            execution = new MojoExecution(felixBundleMojoDescriptor, configuration);
+            MojoExecution execution = new MojoExecution(felixBundleMojoDescriptor, configuration);
             pluginManager.executeMojo(mavenSession, execution);
+
         } catch (Exception e) {
             throw new MojoExecutionException("karaf-boot-maven-plugin failed", e);
         }
     }
 
+    private void complete(Map<String, String> instructions, File bndInst) throws IOException {
+        List<String> lines =  Files.readAllLines(bndInst.toPath());
+        for (String line : lines) {
+            if (!line.contains(":")) {
+                continue;
+            }
+            String name = line.substring(0, line.indexOf(':')).trim();
+            String value = line.substring(line.indexOf(':') + 1).trim();
+            boolean prepend = false;
+            if (name.startsWith("PREPEND-")) {
+                prepend = true;
+                name = name.substring("PREPEND-".length());
+            }
+            if (instructions.containsKey(name)) {
+                if (prepend) {
+                    instructions.put(name, value + "," + instructions.get(name));
+                } else {
+                    instructions.put(name, instructions.get(name) + "," + value);
+                }
+            } else {
+                instructions.put(name, value);
+            }
+        }
+    }
+
 }