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:42 UTC

[23/35] karaf-boot git commit: Renaming dirs, use blueprint-maven-plugin

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/pom.xml b/starters/karaf-boot-starter-jpa/pom.xml
new file mode 100644
index 0000000..c0ce5b8
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/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-jpa</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <version>${osgi.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jpa_2.0_spec</artifactId>
+            <version>1.1</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/137222a0/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/EclipseLink.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/EclipseLink.java b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/EclipseLink.java
new file mode 100644
index 0000000..f1cba0d
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/EclipseLink.java
@@ -0,0 +1,4 @@
+package org.apache.karaf.boot.jpa;
+
+public interface EclipseLink {
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Hibernate.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Hibernate.java b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Hibernate.java
new file mode 100644
index 0000000..ae4dab3
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Hibernate.java
@@ -0,0 +1,91 @@
+package org.apache.karaf.boot.jpa;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.karaf.boot.jpa.PersistentUnit.ProviderProperty;
+
+public interface Hibernate {
+
+    @ProviderProperty("hibernate.query.substitutions")
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.SOURCE)
+    @interface QuerySubstitutions {
+        String value();
+    }
+
+    @ProviderProperty("hibernate.hbm2ddl.auto")
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.SOURCE)
+    @interface Hbm2DdlAuto {
+        Value value();
+        enum Value {
+            Validate,
+            Update,
+            Create,
+            CreateDrop;
+
+            public String toString() {
+                return super.toString().toLowerCase();
+            }
+        }
+    }
+
+    @ProviderProperty("hibernate.dialect")
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.SOURCE)
+    @interface Dialect {
+        Value value();
+        enum Value {
+            Cache71,
+            DataDirectOracle9,
+            DB2390,
+            DB2400,
+            DB2,
+            Derby,
+            Firebird,
+            FrontBase,
+            H2,
+            HSQL,
+            Informix,
+            Ingres10,
+            Ingres9,
+            Ingres,
+            Interbase,
+            JDataStore,
+            Mckoi,
+            MimerSQL,
+            MySQL5,
+            MySQL5InnoDB,
+            MySQL,
+            MySQLInnoDB,
+            MySQLMyISAM,
+            Oracle10g,
+            Oracle8i,
+            Oracle9,
+            Oracle9i,
+            Oracle,
+            Pointbase,
+            PostgresPlus,
+            PostgreSQL,
+            Progress,
+            RDMSOS2200,
+            SAPDB,
+            SQLServer2008,
+            SQLServer,
+            Sybase11,
+            SybaseAnywhere,
+            SybaseASE15,
+            Sybase,
+            Teradata,
+            TimesTen;
+
+            public String toString() {
+                return "org.hibernate.dialect." + super.toString() + "Dialect";
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/OpenJpa.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/OpenJpa.java b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/OpenJpa.java
new file mode 100644
index 0000000..01186fc
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/OpenJpa.java
@@ -0,0 +1,38 @@
+package org.apache.karaf.boot.jpa;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.karaf.boot.jpa.PersistentUnit.ProviderProperty;
+
+public interface OpenJpa {
+
+    @ProviderProperty("openjpa.AutoClear")
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.SOURCE)
+    @interface AutoClear {
+        Value value();
+        enum Value {
+            Datastore, All;
+            public String toString() {
+                return super.toString().toLowerCase();
+            }
+        }
+    }
+
+    @ProviderProperty("openjpa.AutoDetach")
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.SOURCE)
+    @interface AutoDetach {
+        Value value();
+        enum Value {
+            Close, Commit, Nontx_Read;
+            public String toString() {
+                return super.toString().toLowerCase().replace('_', '-');
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/PersistentUnit.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/PersistentUnit.java b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/PersistentUnit.java
new file mode 100644
index 0000000..ada2ef3
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/PersistentUnit.java
@@ -0,0 +1,36 @@
+package org.apache.karaf.boot.jpa;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.SOURCE)
+public @interface PersistentUnit {
+
+    String name();
+
+    String description() default "";
+
+    TransactionType transactionType() default TransactionType.RESOURCE_LOCAL;
+
+    Provider provider() default Provider.Default;
+
+    String providerName() default "";
+
+    String jtaDataSource() default "";
+
+    String nonJtaDataSource() default "";
+
+    // TODO: mapping-file, jar-file, class, exclude-unlisted-classes, shared-cache-mode, validation-mode
+
+    Property[] properties() default {};
+
+
+    @Target(ElementType.ANNOTATION_TYPE)
+    @interface ProviderProperty {
+        String value();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Property.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Property.java b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Property.java
new file mode 100644
index 0000000..5cce58c
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Property.java
@@ -0,0 +1,13 @@
+package org.apache.karaf.boot.jpa;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.SOURCE)
+public @interface Property {
+
+    String name();
+
+    String value();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Provider.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Provider.java b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Provider.java
new file mode 100644
index 0000000..13a62d4
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/Provider.java
@@ -0,0 +1,10 @@
+package org.apache.karaf.boot.jpa;
+
+public enum Provider {
+
+    Default,
+    Hibernate,
+    OpenJpa,
+    EclipseLink;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/TransactionType.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/TransactionType.java b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/TransactionType.java
new file mode 100644
index 0000000..53e76d2
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/TransactionType.java
@@ -0,0 +1,6 @@
+package org.apache.karaf.boot.jpa;
+
+public enum TransactionType {
+    RESOURCE_LOCAL,
+    JTA
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/impl/JpaProcessor.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/impl/JpaProcessor.java b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/impl/JpaProcessor.java
new file mode 100644
index 0000000..4becbc2
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/impl/JpaProcessor.java
@@ -0,0 +1,140 @@
+package org.apache.karaf.boot.jpa.impl;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Messager;
+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.TypeElement;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.karaf.boot.jpa.PersistentUnit;
+import org.apache.karaf.boot.jpa.Property;
+import org.apache.karaf.boot.jpa.Provider;
+
+public class JpaProcessor extends AbstractProcessor {
+
+    public JpaProcessor() {
+    }
+
+    @Override
+    public Set<String> getSupportedAnnotationTypes() {
+        return new HashSet<String>(Arrays.asList(
+                PersistentUnit.class.getName()
+        ));
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        Map<PersistentUnit, List<? extends AnnotationMirror>> units = new HashMap<PersistentUnit, List<? extends AnnotationMirror>>();
+
+
+        for (Element elem : roundEnv.getElementsAnnotatedWith(PersistentUnit.class)) {
+            PersistentUnit pu = elem.getAnnotation(PersistentUnit.class);
+            units.put(pu, elem.getAnnotationMirrors());
+        }
+        if (!units.isEmpty()) {
+            try {
+                Set<String> puNames = new HashSet<String>();
+                FileObject o = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT,
+                        "", "META-INF/persistence.xml");
+                PrintWriter w = new PrintWriter(o.openWriter());
+                w.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+                w.println("<persistence version=\"2.0\" xmlns=\"http://java.sun.com/xml/ns/persistence\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">");
+                for (PersistentUnit pu : units.keySet()) {
+                    if (pu.name() == null || pu.name().isEmpty()) {
+                        throw new IOException("Missing persistent unit name");
+                    }
+                    if (!puNames.add(pu.name())) {
+                        throw new IOException("Duplicate persistent unit name: " + pu.name());
+                    }
+                    w.println("    <persistence-unit name=\"" + pu.name() + "\" transaction-type=\"" + pu.transactionType().toString() + "\">");
+                    if (!pu.description().isEmpty()) {
+                        w.println("        <description>" + pu.description() + "</description>");
+                    }
+                    if (pu.provider() != Provider.Default || !pu.providerName().isEmpty()) {
+                        if (pu.provider() != Provider.Default && !pu.providerName().isEmpty()) {
+                            throw new IOException("At most one of provider and providerName can be used");
+                        }
+                        String name;
+                        if (!pu.providerName().isEmpty()) {
+                            name = pu.providerName();
+                        } else {
+                            switch (pu.provider()) {
+                                case Hibernate:
+                                    name = "org.hibernate.jpa.HibernatePersistenceProvider";
+                                    break;
+                                default:
+                                    // TODO
+                                    throw new IOException("Unsupported provider: " + pu.provider());
+                            }
+                        }
+                        w.println("        <provider>" + name + "</provider>");
+                    }
+                    if (!pu.jtaDataSource().isEmpty()) {
+                        w.println("        <jta-data-source>" + pu.jtaDataSource() + "</jta-data-source>");
+                    }
+                    if (!pu.nonJtaDataSource().isEmpty()) {
+                        w.println("        <non-jta-data-source>" + pu.nonJtaDataSource() + "</non-jta-data-source>");
+                    }
+                    if (pu.properties().length > 0) {
+                        w.println("        <properties>");
+                        for (Property property : pu.properties()) {
+                            w.println("            <property name=\"" + property.name() + "\" value=\"" + property.value() + "\"/>");
+                        }
+
+
+                        for (AnnotationMirror annMirror : units.get(pu)) {
+
+                            String name = null;
+                            for (AnnotationMirror a : processingEnv.getElementUtils().getAllAnnotationMirrors(annMirror.getAnnotationType().asElement())) {
+                                if (a.toString().startsWith("@org.apache.karaf.boot.jpa.PersistentUnit.ProviderProperty")) {
+                                    name = a.getElementValues().values().iterator().next().getValue().toString();
+                                    break;
+                                }
+                            }
+                            if (name != null) {
+                                String value = annMirror.getElementValues().values().iterator().next().getValue().toString();
+                                w.println("            <property name=\"" + name + "\" value=\"" + value + "\"/>");
+                            }
+//                            processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation: " + annMirror);
+//                            processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation type: " + annMirror.getAnnotationType());
+//                            processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation annot: " + annMirror.getAnnotationType().getAnnotationMirrors());
+//                            processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation annot: " + processingEnv.getElementUtils().getAllAnnotationMirrors(annMirror.getAnnotationType().asElement()));
+//                            processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation values: " + annMirror.getElementValues());
+//                            if (annMirror.getAnnotationType().getAnnotation(PersistentUnit.ProviderProperty.class) != null) {
+//                                processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation ok");
+//                            } else {
+//                                processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation nok");
+//                            }
+                        }
+
+                        w.println("        </properties>");
+                    }
+                    w.println("    </persistence-unit>");
+                }
+                w.println("</persistence>");
+                w.close();
+                processingEnv.getMessager().printMessage(Kind.NOTE, "Generated META-INF/persistence.xml");
+            } catch (IOException e) {
+                processingEnv.getMessager().printMessage(Kind.ERROR, "Error: " + e.getMessage());
+            }
+        }
+        return true;
+    }
+
+}

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

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter-karaf/pom.xml
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-karaf/pom.xml b/starters/karaf-boot-starter-karaf/pom.xml
new file mode 100644
index 0000000..32bec48
--- /dev/null
+++ b/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/137222a0/starters/karaf-boot-starter-karaf/src/main/java/org/apache/karaf/boot/karaf/impl/KarafProcessor.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-karaf/src/main/java/org/apache/karaf/boot/karaf/impl/KarafProcessor.java b/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/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/137222a0/starters/karaf-boot-starter-karaf/src/main/resources/META-INF/services/javax.annotation.processing.Processor
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-karaf/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/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/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/137222a0/starters/karaf-boot-starter-shell/pom.xml
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-shell/pom.xml b/starters/karaf-boot-starter-shell/pom.xml
new file mode 100644
index 0000000..28523c7
--- /dev/null
+++ b/starters/karaf-boot-starter-shell/pom.xml
@@ -0,0 +1,52 @@
+<?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-shell</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</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/137222a0/starters/karaf-boot-starter-shell/src/main/java/org/apache/karaf/boot/shell/impl/ShellProcessor.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-shell/src/main/java/org/apache/karaf/boot/shell/impl/ShellProcessor.java b/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/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/137222a0/starters/karaf-boot-starter-shell/src/main/resources/META-INF/services/javax.annotation.processing.Processor
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-shell/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/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/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/137222a0/starters/karaf-boot-starter-web/pom.xml
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-web/pom.xml b/starters/karaf-boot-starter-web/pom.xml
new file mode 100644
index 0000000..54bc3c5
--- /dev/null
+++ b/starters/karaf-boot-starter-web/pom.xml
@@ -0,0 +1,41 @@
+<?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-web</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>3.1.0</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/karaf-boot-starter/pom.xml
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter/pom.xml b/starters/karaf-boot-starter/pom.xml
new file mode 100644
index 0000000..e5b2742
--- /dev/null
+++ b/starters/karaf-boot-starter/pom.xml
@@ -0,0 +1,41 @@
+<?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</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>${osgi.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/starters/pom.xml
----------------------------------------------------------------------
diff --git a/starters/pom.xml b/starters/pom.xml
new file mode 100644
index 0000000..57dbd39
--- /dev/null
+++ b/starters/pom.xml
@@ -0,0 +1,45 @@
+<?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-build</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>karaf-boot-starters</artifactId>
+    <packaging>pom</packaging>
+
+    <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>
+        <module>karaf-boot-starter-jpa</module>
+        <module>karaf-boot-starter-cdi</module>
+        <module>karaf-boot-starter-blueprint</module>
+    </modules>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/tools/karaf-boot-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/tools/karaf-boot-maven-plugin/pom.xml b/tools/karaf-boot-maven-plugin/pom.xml
new file mode 100644
index 0000000..8897be1
--- /dev/null
+++ b/tools/karaf-boot-maven-plugin/pom.xml
@@ -0,0 +1,85 @@
+<?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-tools</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>karaf-boot-maven-plugin</artifactId>
+    <packaging>maven-plugin</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <version>3.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.plugin-tools</groupId>
+            <artifactId>maven-plugin-annotations</artifactId>
+            <version>3.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-core</artifactId>
+            <version>3.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-model</artifactId>
+            <version>3.2.1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+                <version>3.3</version>
+                <configuration>
+                    <goalPrefix>karaf-boot</goalPrefix>
+                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>generate-descriptor</id>
+                        <goals>
+                            <goal>descriptor</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>generate-helpmojo</id>
+                        <goals>
+                            <goal>helpmojo</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..dd88688
--- /dev/null
+++ b/tools/karaf-boot-maven-plugin/src/main/java/org/apache/karaf/boot/maven/GenerateMojo.java
@@ -0,0 +1,124 @@
+package org.apache.karaf.boot.maven;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.BuildPluginManager;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.descriptor.*;
+import org.apache.maven.plugins.annotations.*;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+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;
+import java.util.List;
+import java.util.Map;
+
+@Mojo(name = "generate", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, inheritByDefault = false)
+public class GenerateMojo extends AbstractMojo {
+
+    @Parameter(defaultValue = "${project}", required = true, readonly = true)
+    private MavenProject mavenProject;
+
+    @Parameter(defaultValue = "${session}", required = true, readonly = true)
+    private MavenSession mavenSession;
+
+    @Component
+    private BuildPluginManager pluginManager;
+
+    public void execute() throws MojoExecutionException {
+        try {
+            //
+            // Felix Bundle plugin
+            //
+
+            Map<String, String> instructions = new LinkedHashMap<>();
+            // Starters supplied instructions
+            File bndInst = new File(mavenProject.getBasedir(), "target/classes/META-INF/org.apache.karaf.boot.bnd");
+            if (bndInst.isFile()) {
+                complete(instructions, bndInst);
+                bndInst.delete();
+            }
+            // User supplied instructions
+            bndInst = new File(mavenProject.getBasedir(), "osgi.bnd");
+            if (bndInst.isFile()) {
+                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>" +
+                    "<outputDirectory>${project.build.outputDirectory}</outputDirectory>" +
+                    "<m_mavenSession>${session}</m_mavenSession>" +
+                    "<project>${project}</project>" +
+                    "<buildDirectory>${project.build.directory}</buildDirectory>" +
+                    "<supportedProjectTypes>" +
+                    "<supportedProjectType>jar</supportedProjectType>" +
+                    "<supportedProjectType>bundle</supportedProjectType>" +
+                    "<supportedProjectType>war</supportedProjectType>" +
+                    "</supportedProjectTypes>" +
+                    "<instructions>");
+            for (Map.Entry<String, String> entry : instructions.entrySet()) {
+                config.append("<").append(entry.getKey()).append(">")
+                        .append(entry.getValue())
+                        .append("</").append(entry.getKey()).append(">");
+            }
+            config.append("</instructions>" +
+                    "</configuration>");
+            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");
+            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);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/tools/karaf-boot-maven-plugin/src/main/resources/META-INF/plexus/components.xml
----------------------------------------------------------------------
diff --git a/tools/karaf-boot-maven-plugin/src/main/resources/META-INF/plexus/components.xml b/tools/karaf-boot-maven-plugin/src/main/resources/META-INF/plexus/components.xml
new file mode 100644
index 0000000..6fa2eeb
--- /dev/null
+++ b/tools/karaf-boot-maven-plugin/src/main/resources/META-INF/plexus/components.xml
@@ -0,0 +1,61 @@
+<!--
+ 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.
+-->
+<component-set>
+    <components>
+        <component>
+            <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
+            <role-hint>jar</role-hint>
+            <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
+            <configuration>
+                <lifecycles>
+                    <lifecycle>
+                        <id>default</id>
+                        <phases>
+                            <process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
+                            <compile>org.apache.maven.plugins:maven-compiler-plugin:compile</compile>
+                            <process-classes>org.apache.karaf.boot:karaf-boot-maven-plugin:generate</process-classes>
+                            <process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
+                            <test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
+                            <test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
+                            <install>
+                                org.apache.maven.plugins:maven-install-plugin:install
+                            </install>
+                            <deploy>
+                                org.apache.maven.plugins:maven-deploy-plugin:deploy
+                            </deploy>
+                        </phases>
+                    </lifecycle>
+                </lifecycles>
+            </configuration>
+        </component>
+        <component>
+            <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
+            <role-hint>bundle</role-hint>
+            <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
+            <configuration>
+                <type>jar</type>
+                <includesDependencies>false</includesDependencies>
+                <language>java</language>
+                <extension>jar</extension>
+                <addedToClasspath>true</addedToClasspath>
+                <packaging>jar</packaging>
+            </configuration>
+        </component>
+    </components>
+</component-set>

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/137222a0/tools/pom.xml
----------------------------------------------------------------------
diff --git a/tools/pom.xml b/tools/pom.xml
new file mode 100644
index 0000000..ccb9c88
--- /dev/null
+++ b/tools/pom.xml
@@ -0,0 +1,38 @@
+<?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-build</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>karaf-boot-tools</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>karaf-boot-maven-plugin</module>
+    </modules>
+
+</project>
\ No newline at end of file