You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by da...@apache.org on 2018/04/27 09:43:59 UTC

[sling-slingfeature-maven-plugin] branch master created (now 73c9391)

This is an automated email from the ASF dual-hosted git repository.

davidb pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git.


      at 73c9391  Use felix utils ResourceBuilder and Parser instead of the ManifestParser and ManifestUtil. As with that the feature-support module is empty, remove it.

This branch includes the following new commits:

     new 67c5f3c  Move feature model to whiteboard git
     new 0b61a69  Start changing start level handling to start order handling
     new acde4ef  Refactor start order handling
     new b70cc29  Update to parent pom 33
     new 4201776  [Feature Model] Support separate phases for reading variables
     new a1e9541  Support variables in converting from features to provisioning model
     new 396ff24  Move the process package from the feature api module to the support one.
     new 4a12147  Split feature util into io and assembly parts
     new 562dcb9  Rename process package to builder
     new 0327076  Rename to FileUtils and use constants
     new 68e3a70  Rename packages
     new 47ef2e4  [Sling Feature Model] Split off IO packages into separate module.
     new 5da7069  [Sling Feature Model] Refactor FeatureUtil out of the support module
     new 73c9391  Use felix utils ResourceBuilder and Parser instead of the ManifestParser and ManifestUtil. As with that the feature-support module is empty, remove it.

The 14 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 13/14: [Sling Feature Model] Refactor FeatureUtil out of the support module

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 5da70696792fc109970b106ad374ff9e0666d19d
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Wed Apr 25 13:40:18 2018 +0100

    [Sling Feature Model] Refactor FeatureUtil out of the support module
    
    Also move the Resolver API to the resolver module.
---
 src/main/java/org/apache/sling/feature/maven/Preprocessor.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index 2b50c2b..509e89e 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -235,7 +235,7 @@ public class Preprocessor {
 
             for(final File file : files) {
                 try {
-                    final List<String> features = org.apache.sling.feature.io.FileUtils.parseFeatureRefFile(file);
+                    final List<String> features = org.apache.sling.feature.io.IOUtils.parseFeatureRefFile(file);
                     if ( features.isEmpty() ) {
                         env.logger.debug("Empty feature ref file at " + file);
                     } else {

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 01/14: Move feature model to whiteboard git

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 67c5f3c6396d0e2bacfafdea473cd1effa833f8d
Author: Carsten Ziegeler <cz...@adobe.com>
AuthorDate: Fri Nov 3 15:06:50 2017 +0100

    Move feature model to whiteboard git
---
 pom.xml                                            | 192 ++++++++
 .../feature/maven/ApplicationProjectConfig.java    | 116 +++++
 .../feature/maven/ApplicationProjectInfo.java      |  31 ++
 .../apache/sling/feature/maven/Environment.java    |  35 ++
 .../sling/feature/maven/FeatureConstants.java      |  32 ++
 .../sling/feature/maven/FeatureProjectConfig.java  | 138 ++++++
 .../sling/feature/maven/FeatureProjectInfo.java    |  32 ++
 .../apache/sling/feature/maven/Preprocessor.java   | 515 +++++++++++++++++++++
 .../apache/sling/feature/maven/ProjectHelper.java  | 319 +++++++++++++
 .../apache/sling/feature/maven/ProjectInfo.java    |  27 ++
 .../feature/maven/mojos/AbstractFeatureMojo.java   | 116 +++++
 .../sling/feature/maven/mojos/AttachFeature.java   |  77 +++
 .../mojos/DependencyLifecycleParticipant.java      |  89 ++++
 .../META-INF/m2e/lifecycle-mapping-metadata.xml    |  32 ++
 src/main/resources/META-INF/plexus/components.xml  | 103 +++++
 src/site/markdown/index.md                         |   6 +
 src/site/site.xml                                  |  35 ++
 17 files changed, 1895 insertions(+)

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..0d887cf
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.
+-->
+<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/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>32</version>
+        <relativePath />
+    </parent>
+
+    <artifactId>osgifeature-maven-plugin</artifactId>
+    <version>0.01.7-SNAPSHOT</version>
+    <packaging>maven-plugin</packaging>
+
+    <name>Apache Sling OSGi Feature Maven Plugin</name>
+    <description>
+        Maven Plugin for OSGi Applicatgions
+    </description>
+
+    <properties>
+        <sling.java.version>8</sling.java.version>
+        <maven.version>3.5.0</maven.version>
+        <maven.site.path>${project.artifactId}-archives/${project.artifactId}-LATEST</maven.site.path>
+    </properties>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/tooling/maven/osgifeature-maven-plugin</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/tooling/maven/osgifeature-maven-plugin</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/tooling/maven/osgifeature-maven-plugin</url>
+    </scm>
+
+    <!-- Support for publishing the mvn site. -->
+    <distributionManagement>
+        <site>
+            <id>apache.website</id>
+            <url>scm:svn:https://svn.apache.org/repos/infra/websites/production/sling/content/components/${maven.site.path}</url>
+        </site>
+    </distributionManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.plexus</groupId>
+                <artifactId>plexus-component-metadata</artifactId>
+                <version>1.7.1</version>
+                <executions>
+                    <execution>
+                        <id>generate-metadata</id>
+                        <goals>
+                            <goal>generate-metadata</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>mojo-descriptor</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>descriptor</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>generated-helpmojo</id>
+                        <goals>
+                            <goal>helpmojo</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-scm-publish-plugin</artifactId>
+                <configuration>
+                    <checkoutDirectory>${user.home}/maven-sites/${maven.site.path}</checkoutDirectory>
+                    <tryUpdate>true</tryUpdate>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>src/site/markdown/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature.support</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-core</artifactId>
+            <version>${maven.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <version>${maven.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-artifact</artifactId>
+            <version>${maven.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-compat</artifactId>
+            <version>${maven.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.plugin-tools</groupId>
+            <artifactId>maven-plugin-annotations</artifactId>
+            <version>3.5</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-interactivity-api</artifactId>
+            <version>1.0-alpha-6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-archiver</artifactId>
+            <version>3.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-utils</artifactId>
+            <version>3.0.24</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.shared</groupId>
+            <artifactId>maven-filtering</artifactId>
+            <version>3.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.10.19</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </reporting>
+
+</project>
diff --git a/src/main/java/org/apache/sling/feature/maven/ApplicationProjectConfig.java b/src/main/java/org/apache/sling/feature/maven/ApplicationProjectConfig.java
new file mode 100644
index 0000000..78cd363
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/ApplicationProjectConfig.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven;
+
+import org.apache.maven.artifact.Artifact;
+
+public class ApplicationProjectConfig {
+
+    public static final String CFG_FEATURES = "features";
+
+    public static final String CFG_TEST_FEATURES = "testFeatures";
+
+    public static final String CFG_FEATURE_REFS = "featureRefs";
+
+    public static final String CFG_TEST_FEATURE_REFS = "testFeatureRefs";
+
+    public static final String DEFAULT_FEATURE_DIR = "src/main/osgi/features";
+
+    public static final String DEFAULT_TEST_FEATURE_DIR = "src/test/osgi/features";
+
+    public static final String DEFAULT_REF_DIR = "src/main/osgi/feature-refs";
+
+    public static final String DEFAULT_TEST_REF_DIR = "src/test/osgi/feature-refs";
+
+    private final String featuresDirName;
+
+    private final String featureRefsDirName;
+
+    private final boolean skipAddDep;
+
+    private final String name;
+
+    private final String scope;
+
+    private final boolean isTest;
+
+    public static ApplicationProjectConfig getMainConfig(final ApplicationProjectInfo info) {
+        return new ApplicationProjectConfig(info, false);
+    }
+
+    public static ApplicationProjectConfig getTestConfig(final ApplicationProjectInfo info) {
+        return new ApplicationProjectConfig(info, true);
+    }
+
+    private ApplicationProjectConfig(final ApplicationProjectInfo info, final boolean test) {
+        this.isTest = test;
+        final String featuresDirCfgName;
+        final String featureRefsDirCfgName;
+        final String defaultDir;
+        final String defaultRefDir;
+        final String skipAddDepCfgName;
+        final String defaultSkipValue;
+        if ( test ) {
+            featuresDirCfgName = CFG_TEST_FEATURES;
+            featureRefsDirCfgName = CFG_TEST_FEATURE_REFS;
+            defaultDir = DEFAULT_TEST_FEATURE_DIR;
+            defaultRefDir = DEFAULT_TEST_REF_DIR;
+            skipAddDepCfgName = FeatureProjectConfig.CFG_SKIP_ADD_TEST_FEATURE_DEPENDENCIES;
+            defaultSkipValue = "true";
+            this.scope = Artifact.SCOPE_TEST;
+            this.name = "test features";
+        } else {
+            featuresDirCfgName = CFG_FEATURES;
+            featureRefsDirCfgName = CFG_FEATURE_REFS;
+            defaultDir = DEFAULT_FEATURE_DIR;
+            defaultRefDir = DEFAULT_REF_DIR;
+            skipAddDepCfgName = FeatureProjectConfig.CFG_SKIP_ADD_FEATURE_DEPENDENCIES;
+            defaultSkipValue = "false";
+            this.scope = Artifact.SCOPE_PROVIDED;
+            this.name = "features";
+        }
+        this.featuresDirName = ProjectHelper.getConfigValue(info.plugin, featuresDirCfgName, defaultRefDir);
+        this.featureRefsDirName = ProjectHelper.getConfigValue(info.plugin, featureRefsDirCfgName, defaultDir);
+        final String skipCfg = ProjectHelper.getConfigValue(info.plugin, skipAddDepCfgName, defaultSkipValue);
+        this.skipAddDep = "true".equals(skipCfg.toLowerCase());
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public String getFeatureDir() {
+        return this.featuresDirName;
+    }
+
+    public String getFeatureRefDir() {
+        return this.featuresDirName;
+    }
+
+    public boolean isSkipAddDependencies() {
+        return this.skipAddDep;
+    }
+
+    public String getScope() {
+        return this.scope;
+    }
+
+    public boolean isTestConfig() {
+        return this.isTest;
+    }
+}
+
diff --git a/src/main/java/org/apache/sling/feature/maven/ApplicationProjectInfo.java b/src/main/java/org/apache/sling/feature/maven/ApplicationProjectInfo.java
new file mode 100644
index 0000000..dc0e393
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/ApplicationProjectInfo.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven;
+
+import org.apache.sling.feature.Feature;
+
+import java.util.List;
+
+public class ApplicationProjectInfo extends ProjectInfo {
+
+    public List<Feature> features;
+    public List<Feature> testFeatures;
+
+    public List<Feature> assembledFeatures;
+    public List<Feature> assembledTestFeatures;
+}
+
diff --git a/src/main/java/org/apache/sling/feature/maven/Environment.java b/src/main/java/org/apache/sling/feature/maven/Environment.java
new file mode 100644
index 0000000..ca5592d
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/Environment.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven;
+
+import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.execution.MavenSession;
+import org.codehaus.plexus.logging.Logger;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Environment {
+
+    public ArtifactHandlerManager artifactHandlerManager;
+    public ArtifactResolver resolver;
+    public MavenSession session;
+    public Logger logger;
+    public final Map<String, ProjectInfo> modelProjects = new HashMap<>();
+}
+
diff --git a/src/main/java/org/apache/sling/feature/maven/FeatureConstants.java b/src/main/java/org/apache/sling/feature/maven/FeatureConstants.java
new file mode 100644
index 0000000..96a3b2c
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/FeatureConstants.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven;
+
+public abstract class FeatureConstants {
+
+    public static final String PACKAGING_FEATURE = "osgifeature";
+
+    public static final String PACKAGING_APPLICATION = "osgiapp";
+
+    public static final String CLASSIFIER_FEATURE = "feature";
+
+    public static final String CLASSIFIER_TEST_FEATURE = "testfeature";
+
+    public static final String FEATURE_ARTIFACT_NAME = "feature.json";
+
+    public static final String TEST_FEATURE_ARTIFACT_NAME = "testfeature.json";
+}
diff --git a/src/main/java/org/apache/sling/feature/maven/FeatureProjectConfig.java b/src/main/java/org/apache/sling/feature/maven/FeatureProjectConfig.java
new file mode 100644
index 0000000..a9ba4f5
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/FeatureProjectConfig.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven;
+
+import org.apache.maven.artifact.Artifact;
+
+public class FeatureProjectConfig {
+
+    public static final String CFG_SKIP_ADD_FEATURE_DEPENDENCIES = "skipAddFeatureDependencies";
+
+    public static final String CFG_SKIP_ADD_TEST_FEATURE_DEPENDENCIES = "skipAddTestFeatureDependencies";
+
+    public static final String CFG_FEATURE_FILE = "featureFile";
+
+    public static final String CFG_TEST_FEATURE_FILE = "testFeatureFile";
+
+    public static final String CFG_FEATURE_INLINED = "feature";
+
+    public static final String CFG_TEST_FEATURE_INLINED = "testFeature";
+
+    public static final String CFG_SKIP_ADD_JAR_TO_FEATURE = "skipAddJarToFeature";
+
+    public static final String CFG_SKIP_ADD_JAR_TO_TEST_FEATURE = "skipAddJarToTestFeature";
+
+    public static final String CFG_JAR_START_LEVEL = "jarStartLevel";
+
+    public static final String DEFAULT_FEATURE_FILE = "src/main/osgi/feature.json";
+
+    public static final String DEFAULT_TEST_FEATURE_FILE = "src/test/osgi/feature.json";
+
+    public static final String DEFAULT_START_LEVEL = "20";
+
+    private final String inlinedFeature;
+
+    private final String featureFileName;
+
+    private final boolean skipAddDep;
+
+    private final String name;
+
+    private final String scope;
+
+    private final boolean isTest;
+
+    private final String jarStartLevel;
+
+    private final boolean skipAddJar;
+
+    public static FeatureProjectConfig getMainConfig(final FeatureProjectInfo info) {
+        return new FeatureProjectConfig(info, false);
+    }
+
+    public static FeatureProjectConfig getTestConfig(final FeatureProjectInfo info) {
+        return new FeatureProjectConfig(info, true);
+    }
+
+    private FeatureProjectConfig(final FeatureProjectInfo info, final boolean test) {
+        this.isTest = test;
+        final String inlineCfgName;
+        final String fileCfgName;
+        final String defaultFile;
+        final String skipAddDepCfgName;
+        final String defaultSkipValue;
+        if ( test ) {
+            inlineCfgName = CFG_TEST_FEATURE_INLINED;
+            fileCfgName = CFG_TEST_FEATURE_FILE;
+            defaultFile = DEFAULT_TEST_FEATURE_FILE;
+            this.scope = Artifact.SCOPE_TEST;
+            skipAddDepCfgName = CFG_SKIP_ADD_TEST_FEATURE_DEPENDENCIES;
+            defaultSkipValue = "true";
+            this.name = "test feature";
+            this.skipAddJar = "true".equals(ProjectHelper.getConfigValue(info.plugin, CFG_SKIP_ADD_JAR_TO_TEST_FEATURE, "true"));
+        } else {
+            inlineCfgName = CFG_FEATURE_INLINED;
+            fileCfgName = CFG_TEST_FEATURE_FILE;
+            defaultFile = DEFAULT_FEATURE_FILE;
+            this.scope = Artifact.SCOPE_PROVIDED;
+            skipAddDepCfgName = CFG_SKIP_ADD_FEATURE_DEPENDENCIES;
+            defaultSkipValue = "false";
+            this.name = "feature";
+            this.skipAddJar = "true".equals(ProjectHelper.getConfigValue(info.plugin, CFG_SKIP_ADD_JAR_TO_FEATURE, "true"));
+        }
+        this.inlinedFeature = ProjectHelper.getConfigValue(info.plugin, inlineCfgName, null);
+        this.featureFileName = ProjectHelper.getConfigValue(info.plugin, fileCfgName, defaultFile);
+        final String skipCfg = ProjectHelper.getConfigValue(info.plugin, skipAddDepCfgName, defaultSkipValue);
+        this.skipAddDep = "true".equals(skipCfg.toLowerCase());
+        this.jarStartLevel = ProjectHelper.getConfigValue(info.plugin, CFG_JAR_START_LEVEL, DEFAULT_START_LEVEL);
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public String getInlinedFeature() {
+        return this.inlinedFeature;
+    }
+
+    public String getFeatureFileName() {
+        return this.featureFileName;
+    }
+
+    public boolean isSkipAddDependencies() {
+        return this.skipAddDep;
+    }
+
+    public String getScope() {
+        return this.scope;
+    }
+
+    public boolean isTestConfig() {
+        return this.isTest;
+    }
+
+    public String getJarStartLevel() {
+        return this.jarStartLevel;
+    }
+
+    public boolean isSkipAddJarToFeature() {
+        return this.skipAddJar;
+    }
+
+
+}
+
diff --git a/src/main/java/org/apache/sling/feature/maven/FeatureProjectInfo.java b/src/main/java/org/apache/sling/feature/maven/FeatureProjectInfo.java
new file mode 100644
index 0000000..b0f379b
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/FeatureProjectInfo.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven;
+
+import org.apache.sling.feature.Feature;
+
+public class FeatureProjectInfo extends ProjectInfo {
+
+    public boolean featureDone = false;
+    public boolean testFeatureDone = false;
+
+    public Feature feature;
+    public Feature assembledFeature;
+
+    public Feature testFeature;
+    public Feature assembledTestFeature;
+}
+
diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
new file mode 100644
index 0000000..47a09c5
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -0,0 +1,515 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven;
+
+import org.apache.maven.model.Dependency;
+import org.apache.maven.project.MavenProject;
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.process.BuilderContext;
+import org.apache.sling.feature.process.FeatureBuilder;
+import org.apache.sling.feature.process.FeatureProvider;
+import org.apache.sling.feature.support.FeatureUtil;
+import org.apache.sling.feature.support.json.FeatureJSONReader;
+import org.codehaus.plexus.logging.Logger;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * The processor processes all feature projects.
+ */
+public class Preprocessor {
+
+    /**
+     * Process the provided projects.
+     * @param env The environment with all maven settings and projects
+     */
+    public void process(final Environment env) {
+        for(final ProjectInfo info : env.modelProjects.values()) {
+            if ( info instanceof FeatureProjectInfo ) {
+                final FeatureProjectInfo finfo = (FeatureProjectInfo)info;
+                process(env, finfo, FeatureProjectConfig.getMainConfig(finfo));
+                process(env, finfo, FeatureProjectConfig.getTestConfig(finfo));
+                if ( FeatureConstants.PACKAGING_FEATURE.equals(info.project.getPackaging()) && finfo.feature == null ) {
+                    throw new RuntimeException("Feature project has no feature defined: " + info.project.getId());
+                }
+
+                ProjectHelper.storeProjectInfo(finfo);
+            } else {
+                final ApplicationProjectInfo ainfo = (ApplicationProjectInfo)info;
+                process(env, ainfo, ApplicationProjectConfig.getMainConfig(ainfo));
+                process(env, ainfo, ApplicationProjectConfig.getTestConfig(ainfo));
+
+                ProjectHelper.storeProjectInfo(ainfo);
+            }
+        }
+    }
+
+    /**
+     * Process a single feature project.
+     *
+     * @param env The environment with all maven settings and projects
+     * @param info The project to process.
+     * @param config The configuration for the project.
+     */
+    private void process(final Environment env,
+            final FeatureProjectInfo info,
+            final FeatureProjectConfig config) {
+        if ( (config.isTestConfig() && info.testFeatureDone == true )
+             || (!config.isTestConfig() && info.featureDone == true) ) {
+            env.logger.debug("Return assembled " + config.getName() + " for " + info.project.getId());
+            return;
+        }
+        // prevent recursion and multiple processing
+        if ( config.isTestConfig() ) {
+            info.testFeatureDone = true;
+        } else {
+            info.featureDone = true;
+        }
+        env.logger.debug("Processing " + config.getName() + " in project " + info.project.getId());
+
+        // read project feature, either inlined or from file
+        final Feature feature = readProjectFeature(env.logger, info.project, config);
+        if ( feature == null ) {
+            env.logger.debug("No " + config.getName() + " found in project " + info.project.getId());
+            return;
+        }
+        if ( config.isTestConfig() ) {
+            info.testFeature = feature;
+        } else {
+            info.feature = feature;
+        }
+
+        // process attachments (only for jar or bundle)
+        if ( "jar".equals(info.project.getPackaging())
+             || "bundle".equals(info.project.getPackaging())) {
+            if ( config.isSkipAddJarToFeature() ) {
+                env.logger.debug("Skip adding jar to " + config.getName());
+            } else {
+                final Artifact jar = new Artifact(new ArtifactId(info.project.getGroupId(),
+                        info.project.getArtifactId(),
+                        info.project.getVersion(),
+                        null,
+                        "jar"));
+                feature.getBundles().add(Integer.valueOf(config.getJarStartLevel()), jar);
+            }
+        }
+
+        final Feature assembledFeature = FeatureBuilder.assemble(feature, new BuilderContext(this.createFeatureProvider(env,
+                info,
+                config.isTestConfig(),
+                config.isSkipAddDependencies(),
+                config.getScope(), null)));
+        if ( config.isTestConfig() ) {
+            info.assembledTestFeature = assembledFeature;
+        } else {
+            info.assembledFeature = assembledFeature;
+        }
+
+        if ( config.isSkipAddDependencies() ) {
+            env.logger.debug("Not adding artifacts from feature as dependencies");
+        } else {
+            addDependenciesFromFeature(env, info, assembledFeature, config.getScope());
+        }
+    }
+
+    private void scan(final List<File> files, final File dir, final String ext) {
+        for(final File f : dir.listFiles()) {
+            if ( !f.getName().startsWith(".") ) {
+                if ( f.isDirectory() ) {
+                    scan(files, f, ext);
+                } else if ( f.getName().endsWith("." + ext) ) {
+                    files.add(f);
+                }
+            }
+        }
+    }
+
+    /**
+     * Process a single application project.
+     *
+     * @param env The environment with all maven settings and projects
+     * @param info The project to process.
+     * @param config The configuration for the project.
+     */
+    private void process(final Environment env,
+            final ApplicationProjectInfo info,
+            final ApplicationProjectConfig config) {
+        final List<Feature> featureList = new ArrayList<>();
+        env.logger.debug("Processing " + config.getName() + " in project " + info.project.getId());
+
+        // an application supports two sets of files:
+        // features and references to features
+
+        // feature files first:
+        final File dir = new File(info.project.getBasedir(), config.getFeatureDir());
+        if ( dir.exists() ) {
+            final List<File> files = new ArrayList<>();
+            scan(files, dir, "json");
+
+            for(final File file : files) {
+                // create id in case the file does not contain one
+                // classifier is the hard part, we use the file path/name
+                String fileName = file.getAbsolutePath().substring(dir.getAbsolutePath().length() + 1);
+                fileName = fileName.substring(0, fileName.length() - 5); // remove .json
+                fileName = fileName.replace(File.separatorChar, '_');
+                fileName = fileName.replace('-', '_');
+                final String classifier;
+                if ( config.isTestConfig() ) {
+                    classifier = "test_" + fileName;
+                } else {
+                    classifier = fileName;
+                }
+                final ArtifactId id = new ArtifactId(info.project.getGroupId(),
+                        info.project.getArtifactId(),
+                        info.project.getVersion(),
+                        classifier,
+                        FeatureConstants.PACKAGING_FEATURE);
+
+                // We should pass in an "id" to FeatureJSONReader.read and later on check the id (again, need to handle ref files)
+                try (final FileReader reader = new FileReader(file)) {
+                    final Feature feature = FeatureJSONReader.read(reader, id, file.getAbsolutePath());
+
+                    this.checkFeatureId(id, feature);
+
+                    this.setProjectInfo(info.project, feature);
+                    this.postProcessReadFeature(feature);
+                    featureList.add(feature);
+
+                } catch ( final IOException io) {
+                    throw new RuntimeException("Unable to read feature " + file.getAbsolutePath(), io);
+                }
+            }
+        } else {
+            env.logger.debug("Feature directory " + config.getFeatureDir() + " does not exist in project " + info.project.getId());
+        }
+        final List<Feature> assembledFeatureList = new ArrayList<>();
+        for(final Feature feature : featureList) {
+            final Feature assembledFeature = FeatureBuilder.assemble(feature, new BuilderContext(this.createFeatureProvider(env,
+                    info,
+                    config.isTestConfig(),
+                    config.isSkipAddDependencies(),
+                    config.getScope(),
+                    featureList)));
+            assembledFeatureList.add(assembledFeature);
+        }
+        if ( config.isTestConfig() ) {
+            info.testFeatures = featureList;
+            info.assembledTestFeatures = assembledFeatureList;
+        } else {
+            info.features = featureList;
+            info.assembledFeatures = assembledFeatureList;
+        }
+
+        // and now references
+        final List<Feature> featureRefList = new ArrayList<>();
+        final File refDir = new File(info.project.getBasedir(), config.getFeatureRefDir());
+        if ( refDir.exists() ) {
+            final List<File> files = new ArrayList<>();
+            scan(files, refDir, "ref");
+
+            for(final File file : files) {
+                try {
+                    final List<String> features = FeatureUtil.parseFeatureRefFile(file);
+                    if ( features.isEmpty() ) {
+                        env.logger.debug("Empty feature ref file at " + file);
+                    } else {
+                        for(final String ref : features) {
+                            if ( !ref.startsWith("mvn:") ) {
+                                throw new RuntimeException("Unsupported feature ref in feature ref file at " + file + " : " + ref);
+                            }
+                            final ArtifactId id = ArtifactId.fromMvnUrl(ref);
+                            final Feature feature = this.createFeatureProvider(env, info, config.isTestConfig(), config.isSkipAddDependencies(), config.getScope(), null).provide(id);
+                            if ( feature == null ) {
+                                throw new RuntimeException("Unable to resolve feature " + id);
+                            }
+                            featureRefList.add(feature);
+                        }
+                    }
+                } catch ( final IOException io) {
+                    throw new RuntimeException("Unable to read feature " + file.getAbsolutePath(), io);
+                }
+            }
+        }
+        final List<Feature> assembledFeatureRefList = new ArrayList<>();
+        for(final Feature feature : featureRefList) {
+            final Feature assembledFeature = FeatureBuilder.assemble(feature, new BuilderContext(this.createFeatureProvider(env,
+                    info,
+                    config.isTestConfig(),
+                    config.isSkipAddDependencies(),
+                    config.getScope(),
+                    featureList)));
+            assembledFeatureRefList.add(assembledFeature);
+        }
+        if ( config.isTestConfig() ) {
+            info.testFeatures.addAll(featureRefList);
+            info.assembledTestFeatures.addAll(assembledFeatureRefList);
+        } else {
+            info.features.addAll(featureRefList);
+            info.assembledFeatures.addAll(assembledFeatureRefList);
+        }
+
+        if ( config.isSkipAddDependencies() ) {
+            env.logger.debug("Not adding artifacts from features as dependencies");
+        } else {
+            for(final Feature feature : assembledFeatureList) {
+                addDependenciesFromFeature(env, info, feature, config.getScope());
+            }
+        }
+    }
+
+    /**
+     * Add all dependencies from the feature
+     * @param env The environment
+     * @param info The project info
+     * @param assembledFeature The assembled feature for finding the artifacts.
+     * @param scope The scope which the new dependencies should have
+     */
+    private void addDependenciesFromFeature(
+            final Environment env,
+            final ProjectInfo info,
+            final Feature assembledFeature,
+            final String scope) {
+        for(final Map.Entry<Integer, org.apache.sling.feature.Artifact> entry : assembledFeature.getBundles()) {
+            final ArtifactId a = entry.getValue().getId();
+            if ( a.getGroupId().equals(info.project.getGroupId())
+                 && a.getArtifactId().equals(info.project.getArtifactId())
+                 && a.getVersion().equals(info.project.getVersion()) ) {
+                // skip artifact from the same project
+                env.logger.debug("- skipping dependency " + a.toMvnId());
+                continue;
+            }
+
+            env.logger.debug("- adding dependency " + a.toMvnId());
+            final Dependency dep = ProjectHelper.toDependency(a, scope);
+            info.project.getDependencies().add(dep);
+        }
+        for(final Extension ext : assembledFeature.getExtensions()) {
+            if ( ext.getType() != ExtensionType.ARTIFACTS ) {
+                continue;
+            }
+            for(final org.apache.sling.feature.Artifact art : ext.getArtifacts()) {
+                final ArtifactId a = art.getId();
+                if ( a.getGroupId().equals(info.project.getGroupId())
+                     && a.getArtifactId().equals(info.project.getArtifactId())
+                     && a.getVersion().equals(info.project.getVersion()) ) {
+                    // skip artifact from the same project
+                    env.logger.debug("- skipping dependency " + a.toMvnId());
+                    continue;
+                }
+                env.logger.debug("- adding dependency " + a.toMvnId());
+                final Dependency dep = ProjectHelper.toDependency(a, scope);
+                info.project.getDependencies().add(dep);
+            }
+        }
+    }
+
+    /**
+     * Read the feature for a feature project.
+     * The feature is either inlined in the pom or stored in a file in the project.
+     *
+     * @param logger The logger
+     * @param project The current maven project
+     * @param config The configuration
+     * @return The feature or {@code null}
+     */
+    protected Feature readProjectFeature(
+            final Logger logger,
+            final MavenProject project,
+            final FeatureProjectConfig config) {
+        final File featureFile = new File(project.getBasedir(), config.getFeatureFileName());
+        logger.debug("Checking feature file " + config.getFeatureFileName() + " : " + featureFile.exists());
+        logger.debug("Inlined feature : " + (config.getInlinedFeature() != null));
+
+        if ( config.getInlinedFeature() != null && featureFile.exists() ) {
+            throw new RuntimeException("Only one (feature file or inlined feature) can be specified - but not both");
+        }
+
+        final String classifier;
+        if ( config.isTestConfig() ) {
+            classifier = FeatureConstants.CLASSIFIER_TEST_FEATURE;
+        } else if ( FeatureConstants.PACKAGING_FEATURE.equals(project.getPackaging()) ) {
+            classifier = null;
+        } else {
+            classifier = FeatureConstants.CLASSIFIER_FEATURE;
+        }
+        final ArtifactId id = new ArtifactId(project.getGroupId(),
+                project.getArtifactId(),
+                project.getVersion(),
+                classifier,
+                FeatureConstants.PACKAGING_FEATURE);
+
+        final Feature feature;
+        if ( config.getInlinedFeature() != null ) {
+            logger.debug("Reading inlined model from project " + project.getId());
+            try (final Reader reader = new StringReader(config.getInlinedFeature())) {
+                feature = FeatureJSONReader.read(reader, id, null);
+            } catch ( final IOException io) {
+                throw new RuntimeException("Unable to read inlined feature", io);
+            }
+        } else {
+            if ( !featureFile.exists() ) {
+                logger.debug("Feature file " + featureFile + " in project " + project.getId() + " does not exist.");
+                return null;
+            }
+            logger.debug("Reading feature " + featureFile + " in project " + project.getId());
+            try (final FileReader reader = new FileReader(featureFile)) {
+                feature = FeatureJSONReader.read(reader, id, featureFile.getAbsolutePath());
+            } catch ( final IOException io) {
+                throw new RuntimeException("Unable to read feature " + featureFile, io);
+            }
+        }
+        this.checkFeatureId(id, feature);
+
+        this.setProjectInfo(project, feature);
+
+        // post process and return
+        return postProcessReadFeature(feature);
+    }
+
+    private void checkFeatureId(final ArtifactId id, final Feature feature) {
+        // check feature id
+        if ( !id.getGroupId().equals(feature.getId().getGroupId()) ) {
+            throw new RuntimeException("Wrong group id for feature. It should be " + id.getGroupId() + " but is " + feature.getId().getGroupId());
+        }
+        if ( !id.getArtifactId().equals(feature.getId().getArtifactId()) ) {
+            throw new RuntimeException("Wrong artifact id for feature. It should be " + id.getArtifactId() + " but is " + feature.getId().getArtifactId());
+        }
+        if ( !id.getVersion().equals(feature.getId().getVersion()) ) {
+            throw new RuntimeException("Wrong version for feature. It should be " + id.getVersion() + " but is " + feature.getId().getVersion());
+        }
+    }
+
+    /**
+     * Hook to post process the local feature
+     * @param result The read feature
+     * @return The post processed feature
+     */
+    protected Feature postProcessReadFeature(final Feature result)  {
+        return result;
+    }
+
+    protected void setProjectInfo(final MavenProject project, final Feature feature) {
+        // set title, description, vendor, license
+        if ( feature.getTitle() == null ) {
+            feature.setTitle(project.getName());
+        }
+        if ( feature.getDescription() == null ) {
+            feature.setDescription(project.getDescription());
+        }
+        if ( feature.getVendor() == null && project.getOrganization() != null ) {
+            feature.setVendor(project.getOrganization().getName());
+        }
+        if ( feature.getLicense() == null
+             && project.getLicenses() != null
+             && !project.getLicenses().isEmpty()) {
+            final String license = project.getLicenses().stream()
+                    .filter(l -> l.getName() != null )
+                    .map(l -> l.getName())
+                    .collect(Collectors.joining(", "));
+
+            feature.setLicense(license);
+        }
+    }
+
+    protected FeatureProvider createFeatureProvider(final Environment env,
+            final ProjectInfo info,
+            final boolean isTest,
+            final boolean skipAddDependencies,
+            final String dependencyScope,
+            final List<Feature> projectFeatures) {
+        return new FeatureProvider() {
+
+            @Override
+            public Feature provide(final ArtifactId id) {
+
+                final Dependency dep = ProjectHelper.toDependency(id, dependencyScope);
+                if ( !skipAddDependencies ) {
+
+                    env.logger.debug("- adding feature dependency " + id.toMvnId());
+                    info.project.getDependencies().add(dep);
+                }
+
+                // if it's a project from the current reactor build, we can't resolve it right now
+                final String key = id.getGroupId() + ":" + id.getArtifactId();
+                final ProjectInfo depProjectInfo = env.modelProjects.get(key);
+                if ( depProjectInfo != null ) {
+                    env.logger.debug("Found reactor " + id.getType() + " dependency to project: " + id);
+                    // check if it is a feature project
+                    if ( depProjectInfo instanceof FeatureProjectInfo ) {
+                        final FeatureProjectInfo depInfo = (FeatureProjectInfo)depProjectInfo;
+                        if ( isTest ) {
+                            process(env, depInfo, FeatureProjectConfig.getTestConfig(depInfo));
+                        } else {
+                            process(env, depInfo, FeatureProjectConfig.getMainConfig(depInfo));
+                        }
+                        if ( isTest && depInfo.assembledTestFeature == null ) {
+                            env.logger.error("Unable to get feature " + id.toMvnId() + " : Recursive test feature dependency list including project " + info.project);
+                        } else if ( !isTest && depInfo.assembledFeature == null ) {
+                            env.logger.error("Unable to get feature " + id.toMvnId() + " : Recursive feature dependency list including project " + info.project);
+                        } else {
+
+                            if ( isTest ) {
+                                return depInfo.testFeature;
+                            } else {
+                                return depInfo.feature;
+                            }
+                        }
+                    } else {
+                        // we only support a dependency to *this* application project
+                        final ApplicationProjectInfo depInfo = (ApplicationProjectInfo)depProjectInfo;
+                        if ( depInfo != info) {
+                            env.logger.error("Unable to get feature " + id.toMvnId() + " : Feature dependency is to a different application project from " + info.project);
+                            return null;
+                        }
+                        if ( projectFeatures != null ) {
+                            for(final Feature f : projectFeatures) {
+                                if ( f.getId().equals(id)) {
+                                    return f;
+                                }
+                            }
+                        }
+                        return null;
+                    }
+                } else {
+                    env.logger.debug("Found external " + id.getType() + " dependency: " + id);
+
+                    // "external" dependency, we can already resolve it
+                    final File featureFile = ProjectHelper.getOrResolveArtifact(info.project, env.session, env.artifactHandlerManager, env.resolver, id).getFile();
+                    try (final FileReader r = new FileReader(featureFile)) {
+                        return FeatureJSONReader.read(r, featureFile.getAbsolutePath());
+                    } catch ( final IOException ioe) {
+                        env.logger.error("Unable to read feature file from " + featureFile, ioe);
+                    }
+                }
+
+                return null;
+            }
+        };
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
new file mode 100644
index 0000000..a314113
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
@@ -0,0 +1,319 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.feature.maven;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
+import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
+import org.apache.maven.artifact.resolver.ArtifactResolutionException;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
+import org.apache.maven.project.MavenProject;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.support.json.FeatureJSONReader;
+import org.apache.sling.feature.support.json.FeatureJSONWriter;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public abstract class ProjectHelper {
+
+    /** Read feature. */
+    private static final String RAW_FEATURE_JSON = Feature.class.getName() + "/rawmain.json";
+    private static final String RAW_TEST_FEATURE_JSON = Feature.class.getName() + "/rawtest.json";
+
+    /** Assembled feature. */
+    private static final String ASSEMBLED_FEATURE_JSON = Feature.class.getName() + "/assembledmain.json";
+    private static final String ASSEMBLED_TEST_FEATURE_JSON = Feature.class.getName() + "/assembledtest.json";
+
+    private static void store(final MavenProject project, final String key, final Feature feature) {
+        if ( feature != null ) {
+            // we have to serialize as the dependency lifecycle participant uses a different class loader (!)
+            try ( final StringWriter w1 = new StringWriter() ) {
+                FeatureJSONWriter.write(w1, feature);
+                project.setContextValue(key, w1.toString());
+            } catch ( final IOException ioe) {
+                throw new RuntimeException(ioe.getMessage(), ioe);
+            }
+        }
+    }
+
+    private static void store(final MavenProject project, final String key, final List<Feature> features) {
+        if ( features != null && !features.isEmpty()) {
+            project.setContextValue(key, features.size());
+            // we have to serialize as the dependency lifecycle participant uses a different class loader (!)
+            int index = 0;
+            for(final Feature f : features) {
+                try ( final StringWriter w1 = new StringWriter() ) {
+                    FeatureJSONWriter.write(w1, f);
+                    project.setContextValue(key + "_" + String.valueOf(index), w1.toString());
+                    index++;
+                } catch ( final IOException ioe) {
+                    throw new RuntimeException(ioe.getMessage(), ioe);
+                }
+            }
+        }
+    }
+
+    private static Feature getFeature(final MavenProject project, final String key) {
+        final String cacheKey = key + "-cache";
+        Feature result = null;
+        try {
+            result = (Feature) project.getContextValue(cacheKey);
+        } catch ( final Exception e) {
+            // if we get a class cast exception, we read again
+        }
+        if ( result == null ) {
+            final String text = (String)project.getContextValue(key);
+            if ( text == null ) {
+                result = null;
+            } else {
+                try ( final StringReader r = new StringReader(text) ) {
+                    result = FeatureJSONReader.read(r, project.getId());
+                    project.setContextValue(cacheKey, result);
+                } catch ( final IOException ioe) {
+                    throw new RuntimeException(ioe.getMessage(), ioe);
+                }
+            }
+        }
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static List<Feature> getFeatures(final MavenProject project, final String key) {
+        final String cacheKey = key + "-cache";
+        List<Feature> result = null;
+        try {
+            result = (List<Feature>) project.getContextValue(cacheKey);
+        } catch ( final Exception e) {
+            // if we get a class cast exception, we read again
+        }
+        if ( result == null ) {
+            final Integer size = (Integer)project.getContextValue(key);
+            if ( size != null ) {
+                result = new ArrayList<>();
+                for(int i=0; i<size;i++) {
+                    final String text = (String)project.getContextValue(key + "_" + String.valueOf(i));
+                    if ( text == null ) {
+                        throw new RuntimeException("Unable to get feature from internal store.");
+                    }
+                    try ( final StringReader r = new StringReader(text) ) {
+                        final Feature feature = FeatureJSONReader.read(r, project.getId());
+                        result.add(feature);
+                    } catch ( final IOException ioe) {
+                        throw new RuntimeException(ioe.getMessage(), ioe);
+                    }
+                }
+                project.setContextValue(cacheKey, result);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Store all relevant information about the project for plugins to be
+     * retrieved
+     * @param info The project info
+     */
+    public static void storeProjectInfo(final FeatureProjectInfo info) {
+        store(info.project, RAW_FEATURE_JSON, info.feature);
+        store(info.project, RAW_TEST_FEATURE_JSON, info.testFeature);
+        store(info.project, ASSEMBLED_FEATURE_JSON, info.assembledFeature);
+        store(info.project, ASSEMBLED_TEST_FEATURE_JSON, info.assembledTestFeature);
+    }
+
+    /**
+     * Get the assembled feature from the project
+     * @param project The maven projet
+     * @return The assembled feature or {@code null}
+     */
+    public static Feature getAssembledFeature(final MavenProject project) {
+        return getFeature(project, ASSEMBLED_FEATURE_JSON);
+    }
+
+    /**
+     * Get the raw feature from the project
+     * @param project The maven projet
+     * @return The raw feature or {@code null}
+     */
+    public static Feature getFeature(final MavenProject project) {
+        return getFeature(project, RAW_FEATURE_JSON);
+    }
+
+    /**
+     * Get the assembled test feature from the project
+     * @param project The maven projet
+     * @return The assembled feature or {@code null}
+     */
+    public static Feature getAssembledTestFeature(final MavenProject project) {
+        return getFeature(project, ASSEMBLED_TEST_FEATURE_JSON);
+    }
+
+    /**
+     * Get the raw test feature from the project
+     * @param project The maven projet
+     * @return The raw feature or {@code null}
+     */
+    public static Feature getTestFeature(final MavenProject project) {
+        return getFeature(project, RAW_TEST_FEATURE_JSON);
+    }
+
+    /**
+     * Store all relevant information about the project for plugins to be
+     * retrieved
+     * @param info The project info
+     */
+    public static void storeProjectInfo(final ApplicationProjectInfo info) {
+        store(info.project, RAW_FEATURE_JSON, info.features);
+        store(info.project, RAW_TEST_FEATURE_JSON, info.testFeatures);
+        store(info.project, ASSEMBLED_FEATURE_JSON, info.assembledFeatures);
+        store(info.project, ASSEMBLED_TEST_FEATURE_JSON, info.assembledTestFeatures);
+    }
+
+    /**
+     * Get the assembled features from the project
+     * @param project The maven projet
+     * @return The assembled features or {@code null}
+     */
+    public static List<Feature> getAssembledFeatures(final MavenProject project) {
+        return getFeatures(project, ASSEMBLED_FEATURE_JSON);
+    }
+
+    /**
+     * Get the raw feature from the project
+     * @param project The maven projet
+     * @return The raw features or {@code null}
+     */
+    public static List<Feature> getFeatures(final MavenProject project) {
+        return getFeatures(project, RAW_FEATURE_JSON);
+    }
+
+    /**
+     * Get the assembled test feature from the project
+     * @param project The maven projet
+     * @return The assembled features or {@code null}
+     */
+    public static List<Feature> getAssembledTestFeatures(final MavenProject project) {
+        return getFeatures(project, ASSEMBLED_TEST_FEATURE_JSON);
+    }
+
+    /**
+     * Get the raw test feature from the project
+     * @param project The maven projet
+     * @return The raw features or {@code null}
+     */
+    public static List<Feature> getTestFeatures(final MavenProject project) {
+        return getFeatures(project, RAW_TEST_FEATURE_JSON);
+    }
+
+    /**
+     * Gets a configuration value for a plugin if it is set in the configuration for
+     * the plugin or any configuration for an execution of the plugin.
+     * @param plugin Plugin
+     * @param name Configuration parameter.
+     * @param defaultValue The default value if no configuration is found.
+     * @return The default value if nothing is configured, the value otherwise.
+     * @throws RuntimeException If more than one value is configured
+     */
+    public static String getConfigValue(final Plugin plugin,
+            final String name,
+            final String defaultValue) {
+        final Set<String> values = new HashSet<>();
+        final Xpp3Dom config = plugin == null ? null : (Xpp3Dom)plugin.getConfiguration();
+        final Xpp3Dom globalNode = (config == null ? null : config.getChild(name));
+        if ( globalNode != null ) {
+            values.add(globalNode.getValue());
+        }
+        for(final PluginExecution exec : plugin.getExecutions()) {
+            final Xpp3Dom cfg = (Xpp3Dom)exec.getConfiguration();
+            final Xpp3Dom pluginNode = (cfg == null ? null : cfg.getChild(name));
+            if ( pluginNode != null ) {
+                values.add(pluginNode.getValue());
+            }
+        }
+        if ( values.size() > 1 ) {
+            throw new RuntimeException("More than one value configured in plugin (executions) of "
+                    + plugin.getKey() + " for " + name + " : " + values);
+        }
+        return values.isEmpty() ? defaultValue : values.iterator().next();
+    }
+
+    /**
+     * Get a resolved Artifact from the coordinates provided
+     *
+     * @return the artifact, which has been resolved.
+     */
+    public static Artifact getOrResolveArtifact(final MavenProject project,
+            final MavenSession session,
+            final ArtifactHandlerManager artifactHandlerManager,
+            final ArtifactResolver resolver,
+            final ArtifactId id) {
+        final Set<Artifact> artifacts = project.getDependencyArtifacts();
+        for(final Artifact artifact : artifacts) {
+            if ( artifact.getGroupId().equals(id.getGroupId())
+               && artifact.getArtifactId().equals(id.getArtifactId())
+               && artifact.getVersion().equals(id.getVersion())
+               && artifact.getType().equals(id.getVersion())
+               && ((id.getClassifier() == null && artifact.getClassifier() == null) || (id.getClassifier() != null && id.getClassifier().equals(artifact.getClassifier()))) ) {
+                return artifact;
+            }
+        }
+        final Artifact prjArtifact = new DefaultArtifact(id.getGroupId(),
+                id.getArtifactId(),
+                VersionRange.createFromVersion(id.getVersion()),
+                Artifact.SCOPE_PROVIDED,
+                id.getType(),
+                id.getClassifier(),
+                artifactHandlerManager.getArtifactHandler(id.getType()));
+        try {
+            resolver.resolve(prjArtifact, project.getRemoteArtifactRepositories(), session.getLocalRepository());
+        } catch (final ArtifactResolutionException | ArtifactNotFoundException e) {
+            throw new RuntimeException("Unable to get artifact for " + id.toMvnId(), e);
+        }
+        return prjArtifact;
+    }
+
+    public static String toString(final Dependency d) {
+        return "Dependency {groupId=" + d.getGroupId() + ", artifactId=" + d.getArtifactId() + ", version=" + d.getVersion() +
+                (d.getClassifier() != null ? ", classifier=" + d.getClassifier() : "") +
+                ", type=" + d.getType() + "}";
+    }
+
+    public static Dependency toDependency(final ArtifactId id, final String scope) {
+        final Dependency dep = new Dependency();
+        dep.setGroupId(id.getGroupId());
+        dep.setArtifactId(id.getArtifactId());
+        dep.setVersion(id.getVersion());
+        dep.setType(id.getType());
+        dep.setClassifier(id.getClassifier());
+        dep.setScope(scope);
+
+        return dep;
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/maven/ProjectInfo.java b/src/main/java/org/apache/sling/feature/maven/ProjectInfo.java
new file mode 100644
index 0000000..6e3fa0d
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/ProjectInfo.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven;
+
+import org.apache.maven.model.Plugin;
+import org.apache.maven.project.MavenProject;
+
+public class ProjectInfo {
+
+    public MavenProject project;
+    public Plugin       plugin;
+}
+
diff --git a/src/main/java/org/apache/sling/feature/maven/mojos/AbstractFeatureMojo.java b/src/main/java/org/apache/sling/feature/maven/mojos/AbstractFeatureMojo.java
new file mode 100644
index 0000000..7c7e2ea
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/AbstractFeatureMojo.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.feature.maven.mojos;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectHelper;
+import org.apache.sling.feature.maven.FeatureProjectConfig;
+
+import java.io.File;
+
+/**
+ * Base class for all mojos.
+ */
+public abstract class AbstractFeatureMojo extends AbstractMojo {
+
+    /**
+     * The feature file..
+     * This parameter is evaluated in the {@link DependencyLifecycleParticipant}.
+     */
+    @Parameter(name = FeatureProjectConfig.CFG_FEATURE_FILE,
+            defaultValue="${basedir}/" + FeatureProjectConfig.DEFAULT_FEATURE_FILE)
+    private File featureFile;
+
+    /**
+     * The test feature file..
+     * This parameter is evaluated in the {@link DependencyLifecycleParticipant}.
+     */
+    @Parameter(name = FeatureProjectConfig.CFG_TEST_FEATURE_FILE,
+            defaultValue="${basedir}/" + FeatureProjectConfig.DEFAULT_TEST_FEATURE_FILE)
+    private File testFeatureFile;
+
+    /**
+     * Inlined model.
+     * This parameter is evaluated in the {@link DependencyLifecycleParticipant}.
+     */
+    @Parameter(name = FeatureProjectConfig.CFG_FEATURE_INLINED)
+    private String feature;
+
+    /**
+     * Inlined test model.
+     * This parameter is evaluated in the {@link DependencyLifecycleParticipant}.
+     */
+    @Parameter(name = FeatureProjectConfig.CFG_TEST_FEATURE_INLINED)
+    private String testFeature;
+
+    /**
+     * If set to {@code true} the artifacts from the feature are not as dependencies to the project.
+     * This parameter is evaluated in the {@link DependencyLifecycleParticipant}.
+     */
+    @Parameter(name=FeatureProjectConfig.CFG_SKIP_ADD_FEATURE_DEPENDENCIES,
+            defaultValue="false")
+    private boolean skipAddFeatureDependencies;
+
+    /**
+     * If set to {@code true} the artifacts from the test feature are not as dependencies to the project.
+     * This parameter is evaluated in the {@link DependencyLifecycleParticipant}.
+     */
+    @Parameter(name=FeatureProjectConfig.CFG_SKIP_ADD_TEST_FEATURE_DEPENDENCIES,
+            defaultValue="true")
+    private boolean skipAddTestFeatureDependencies;
+
+    /**
+     * If set to {@code true} the main jar artifact is not added to the feature.
+     * This parameter is evaluated in the {@link DependencyLifecycleParticipant}.
+     */
+    @Parameter(name=FeatureProjectConfig.CFG_SKIP_ADD_JAR_TO_FEATURE,
+            defaultValue="false")
+    private boolean skipAddJarToFeature;
+
+    /**
+     * If set to {@code true} the main jar artifact is not added to the test feature.
+     * This parameter is evaluated in the {@link DependencyLifecycleParticipant}.
+     */
+    @Parameter(name=FeatureProjectConfig.CFG_SKIP_ADD_JAR_TO_TEST_FEATURE,
+            defaultValue="false")
+    private boolean skipAddJarToTestFeature;
+
+    /**
+     * The start level for the attached jar/bundle.
+     * This parameter is evaluated in the {@link DependencyLifecycleParticipant}.
+     */
+    @Parameter(name=FeatureProjectConfig.CFG_JAR_START_LEVEL,
+            defaultValue=FeatureProjectConfig.DEFAULT_START_LEVEL)
+    private int jarStartLevel;
+
+    @Parameter(property = "project", readonly = true, required = true)
+    protected MavenProject project;
+
+    @Parameter(property = "session", readonly = true, required = true)
+    protected MavenSession mavenSession;
+
+    @Component
+    protected MavenProjectHelper projectHelper;
+
+    protected File getTmpDir() {
+        return new File(this.project.getBuild().getDirectory(), "osgifeature-tmp");
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/maven/mojos/AttachFeature.java b/src/main/java/org/apache/sling/feature/maven/mojos/AttachFeature.java
new file mode 100644
index 0000000..79c5c23
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/AttachFeature.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven.mojos;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.maven.FeatureConstants;
+import org.apache.sling.feature.maven.ProjectHelper;
+import org.apache.sling.feature.support.json.FeatureJSONWriter;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Attach the feature as a project artifact.
+ */
+@Mojo(name = "attach-feature",
+      defaultPhase = LifecyclePhase.PACKAGE,
+      requiresDependencyResolution = ResolutionScope.TEST,
+      threadSafe = true
+    )
+public class AttachFeature extends AbstractFeatureMojo {
+
+    private void attach(final Feature feature,
+            final String artifactName,
+            final String classifier)
+    throws MojoExecutionException {
+        if ( feature != null ) {
+
+            // write the feature
+            final File outputFile = new File(this.project.getBuild().getDirectory() + File.separatorChar + artifactName);
+            outputFile.getParentFile().mkdirs();
+
+            try ( final Writer writer = new FileWriter(outputFile)) {
+                FeatureJSONWriter.write(writer, feature);
+            } catch (final IOException e) {
+                throw new MojoExecutionException("Unable to write feature to " + outputFile, e);
+            }
+
+            // if this project is a feature, it's the main artifact
+            if ( project.getPackaging().equals(FeatureConstants.PACKAGING_FEATURE)
+                 && (FeatureConstants.CLASSIFIER_FEATURE.equals(classifier))) {
+                project.getArtifact().setFile(outputFile);
+            } else {
+                // otherwise attach it as an additional artifact
+                projectHelper.attachArtifact(project, FeatureConstants.PACKAGING_FEATURE,
+                    classifier, outputFile);
+            }
+        }
+    }
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        attach(ProjectHelper.getFeature(this.project), FeatureConstants.FEATURE_ARTIFACT_NAME, FeatureConstants.CLASSIFIER_FEATURE);
+        attach(ProjectHelper.getTestFeature(this.project), FeatureConstants.TEST_FEATURE_ARTIFACT_NAME, FeatureConstants.CLASSIFIER_TEST_FEATURE);
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/maven/mojos/DependencyLifecycleParticipant.java b/src/main/java/org/apache/sling/feature/maven/mojos/DependencyLifecycleParticipant.java
new file mode 100644
index 0000000..ba53623
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/DependencyLifecycleParticipant.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.feature.maven.mojos;
+
+import org.apache.maven.AbstractMavenLifecycleParticipant;
+import org.apache.maven.MavenExecutionException;
+import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.project.MavenProject;
+import org.apache.sling.feature.maven.ApplicationProjectInfo;
+import org.apache.sling.feature.maven.Environment;
+import org.apache.sling.feature.maven.FeatureConstants;
+import org.apache.sling.feature.maven.FeatureProjectInfo;
+import org.apache.sling.feature.maven.Preprocessor;
+import org.apache.sling.feature.maven.ProjectInfo;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * Maven lifecycle participant which adds the artifacts of the model to the dependencies.
+ */
+@Component(role = AbstractMavenLifecycleParticipant.class)
+public class DependencyLifecycleParticipant extends AbstractMavenLifecycleParticipant {
+
+    /**
+     * The plugin ID consists of <code>groupId:artifactId</code>, see {@link Plugin#constructKey(String, String)}
+     */
+    private static final String PLUGIN_ID = "org.apache.sling:osgifeature-maven-plugin";
+
+    @Requirement
+    private Logger logger;
+
+    @Requirement
+    private ArtifactHandlerManager artifactHandlerManager;
+
+    /**
+     * Used to look up Artifacts in the remote repository.
+     *
+     */
+    @Requirement
+    private ArtifactResolver resolver;
+
+    @Override
+    public void afterProjectsRead(final MavenSession session) throws MavenExecutionException {
+        final Environment env = new Environment();
+        env.artifactHandlerManager = artifactHandlerManager;
+        env.resolver = resolver;
+        env.logger = logger;
+        env.session = session;
+
+        logger.debug("Searching for project using plugin '" + PLUGIN_ID + "'...");
+
+        for (final MavenProject project : session.getProjects()) {
+            // consider all projects where this plugin is configured
+            Plugin plugin = project.getPlugin(PLUGIN_ID);
+            if (plugin != null) {
+                logger.debug("Found project " + project.getId() + " using " + PLUGIN_ID);
+                final ProjectInfo info;
+                if ( FeatureConstants.PACKAGING_APPLICATION.equals(project.getPackaging()) ) {
+                    info = new ApplicationProjectInfo();
+                } else {
+                    info = new FeatureProjectInfo();
+                }
+                info.plugin = plugin;
+                info.project = project;
+                env.modelProjects.put(project.getGroupId() + ":" + project.getArtifactId(), info);
+            }
+        }
+
+        new Preprocessor().process(env);
+    }
+}
diff --git a/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml b/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
new file mode 100644
index 0000000..0f2b325
--- /dev/null
+++ b/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
@@ -0,0 +1,32 @@
+<!--
+ 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.
+-->
+<lifecycleMappingMetadata>
+    <pluginExecutions>
+        <pluginExecution>
+            <pluginExecutionFilter>
+                <goals>
+                    <goal>attach-feature</goal>
+                </goals>
+            </pluginExecutionFilter>
+            <action>
+                <ignore/>
+            </action>
+        </pluginExecution>
+    </pluginExecutions>
+</lifecycleMappingMetadata>
diff --git a/src/main/resources/META-INF/plexus/components.xml b/src/main/resources/META-INF/plexus/components.xml
new file mode 100644
index 0000000..6933d3b
--- /dev/null
+++ b/src/main/resources/META-INF/plexus/components.xml
@@ -0,0 +1,103 @@
+<!--
+ 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>osgifeature</role-hint>
+      <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
+      <configuration>
+        <lifecycles>
+          <lifecycle>
+            <id>default</id>
+            <phases>
+              <package>org.apache.sling:slingstart-maven-plugin:attach-slingfeature</package>
+              <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.lifecycle.mapping.LifecycleMapping</role>
+      <role-hint>osgiapp</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-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>
+              <prepare-package>org.apache.sling:slingstart-maven-plugin:prepare-package</prepare-package>              
+              <package>
+                  org.apache.sling:slingstart-maven-plugin:attach-slingfeature,
+                  org.apache.sling:slingstart-maven-plugin:package
+              </package>
+              <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>osgifeature</role-hint>
+      <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
+      <configuration>
+        <type>osgifeature</type>
+        <includesDependencies>false</includesDependencies>
+        <language>json</language>
+        <extension>json</extension>
+        <addedToClasspath>false</addedToClasspath>
+      </configuration>
+    </component>
+    <component>
+      <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
+      <role-hint>osgiapp</role-hint>
+      <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
+      <configuration>
+        <type>osgiapp</type>
+        <includesDependencies>false</includesDependencies>
+        <language>java</language>
+        <extension>jar</extension>
+        <addedToClasspath>false</addedToClasspath>
+      </configuration>
+    </component>
+    <component>
+      <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
+      <role-hint>osgijar</role-hint>
+      <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
+      <configuration>
+        <type>osgijar</type>
+        <includesDependencies>false</includesDependencies>
+        <language>java</language>
+        <extension>zip</extension>
+        <addedToClasspath>false</addedToClasspath>
+      </configuration>
+    </component>
+  </components>
+</component-set>
diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md
new file mode 100644
index 0000000..bd08e61
--- /dev/null
+++ b/src/site/markdown/index.md
@@ -0,0 +1,6 @@
+OSGiMaven Plugin
+================
+
+Maven Plugin for OSGi Applications
+
+See [Goals](plugin-info.html) for a list of supported goals.
diff --git a/src/site/site.xml b/src/site/site.xml
new file mode 100644
index 0000000..9abab11
--- /dev/null
+++ b/src/site/site.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project>
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-fluido-skin</artifactId>
+    <version>1.6</version>
+  </skin>
+  <body>
+    <menu name="Overview">
+      <item name="Introduction" href="index.html"/>
+      <item name="Goals" href="plugin-info.html"/>
+    </menu>
+    <menu ref="reports"/>
+  </body>
+</project>

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 07/14: Move the process package from the feature api module to the support one.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 396ff24e330949c50f0f8f838456fc18a86e2435
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Wed Apr 11 16:51:50 2018 +0100

    Move the process package from the feature api module to the support one.
    
    Also move the associated tests.
---
 src/main/java/org/apache/sling/feature/maven/Preprocessor.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index 4e2f08b..65191a2 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -23,12 +23,12 @@ import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.process.BuilderContext;
-import org.apache.sling.feature.process.FeatureBuilder;
-import org.apache.sling.feature.process.FeatureProvider;
 import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.json.FeatureJSONReader;
 import org.apache.sling.feature.support.json.FeatureJSONReader.SubstituteVariables;
+import org.apache.sling.feature.support.process.BuilderContext;
+import org.apache.sling.feature.support.process.FeatureBuilder;
+import org.apache.sling.feature.support.process.FeatureProvider;
 import org.codehaus.plexus.logging.Logger;
 
 import java.io.File;

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 14/14: Use felix utils ResourceBuilder and Parser instead of the ManifestParser and ManifestUtil. As with that the feature-support module is empty, remove it.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 73c939146bdd196ca4caf52e2f3e1e3d60d542d0
Author: Karl Pauls <kp...@adobe.com>
AuthorDate: Thu Apr 26 12:00:25 2018 +0200

    Use felix utils ResourceBuilder and Parser instead of the ManifestParser and ManifestUtil. As with that the feature-support module is empty, remove it.
---
 pom.xml | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/pom.xml b/pom.xml
index ec05534..0d099b6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -119,11 +119,6 @@
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
         <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.feature.support</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-core</artifactId>
             <version>${maven.version}</version>

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 08/14: Split feature util into io and assembly parts

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 4a121475db1d281b9e6a376e5ecd08cabcfa2cbc
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue Apr 17 16:56:40 2018 +0200

    Split feature util into io and assembly parts
---
 .../apache/sling/feature/maven/Preprocessor.java    | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index 65191a2..6c1a3ef 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -16,6 +16,15 @@
  */
 package org.apache.sling.feature.maven;
 
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
 import org.apache.maven.model.Dependency;
 import org.apache.maven.project.MavenProject;
 import org.apache.sling.feature.Artifact;
@@ -23,7 +32,6 @@ import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.json.FeatureJSONReader;
 import org.apache.sling.feature.support.json.FeatureJSONReader.SubstituteVariables;
 import org.apache.sling.feature.support.process.BuilderContext;
@@ -31,15 +39,6 @@ import org.apache.sling.feature.support.process.FeatureBuilder;
 import org.apache.sling.feature.support.process.FeatureProvider;
 import org.codehaus.plexus.logging.Logger;
 
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
 /**
  * The processor processes all feature projects.
  */
@@ -236,7 +235,7 @@ public class Preprocessor {
 
             for(final File file : files) {
                 try {
-                    final List<String> features = FeatureUtil.parseFeatureRefFile(file);
+                    final List<String> features = org.apache.sling.feature.support.io.FeatureUtil.parseFeatureRefFile(file);
                     if ( features.isEmpty() ) {
                         env.logger.debug("Empty feature ref file at " + file);
                     } else {

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 09/14: Rename process package to builder

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 562dcb9786c81b072aa0921661ad9fd04786aaef
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed Apr 18 09:34:13 2018 +0200

    Rename process package to builder
---
 src/main/java/org/apache/sling/feature/maven/Preprocessor.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index 6c1a3ef..9d7f6b6 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -32,11 +32,11 @@ import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.builder.BuilderContext;
+import org.apache.sling.feature.builder.FeatureBuilder;
+import org.apache.sling.feature.builder.FeatureProvider;
 import org.apache.sling.feature.support.json.FeatureJSONReader;
 import org.apache.sling.feature.support.json.FeatureJSONReader.SubstituteVariables;
-import org.apache.sling.feature.support.process.BuilderContext;
-import org.apache.sling.feature.support.process.FeatureBuilder;
-import org.apache.sling.feature.support.process.FeatureProvider;
 import org.codehaus.plexus.logging.Logger;
 
 /**

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 11/14: Rename packages

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 68e3a701f34d8c6051ab740553e44c602edac9b7
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed Apr 18 10:26:45 2018 +0200

    Rename packages
---
 src/main/java/org/apache/sling/feature/maven/Preprocessor.java      | 6 +++---
 src/main/java/org/apache/sling/feature/maven/ProjectHelper.java     | 6 +++---
 .../java/org/apache/sling/feature/maven/mojos/AttachFeature.java    | 2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index a2665f8..2b50c2b 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -35,8 +35,8 @@ import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.builder.BuilderContext;
 import org.apache.sling.feature.builder.FeatureBuilder;
 import org.apache.sling.feature.builder.FeatureProvider;
-import org.apache.sling.feature.support.json.FeatureJSONReader;
-import org.apache.sling.feature.support.json.FeatureJSONReader.SubstituteVariables;
+import org.apache.sling.feature.io.json.FeatureJSONReader;
+import org.apache.sling.feature.io.json.FeatureJSONReader.SubstituteVariables;
 import org.codehaus.plexus.logging.Logger;
 
 /**
@@ -235,7 +235,7 @@ public class Preprocessor {
 
             for(final File file : files) {
                 try {
-                    final List<String> features = org.apache.sling.feature.support.io.FileUtils.parseFeatureRefFile(file);
+                    final List<String> features = org.apache.sling.feature.io.FileUtils.parseFeatureRefFile(file);
                     if ( features.isEmpty() ) {
                         env.logger.debug("Empty feature ref file at " + file);
                     } else {
diff --git a/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
index ce3314c..c4d1071 100644
--- a/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
+++ b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
@@ -30,9 +30,9 @@ import org.apache.maven.model.PluginExecution;
 import org.apache.maven.project.MavenProject;
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.support.json.FeatureJSONReader;
-import org.apache.sling.feature.support.json.FeatureJSONReader.SubstituteVariables;
-import org.apache.sling.feature.support.json.FeatureJSONWriter;
+import org.apache.sling.feature.io.json.FeatureJSONReader;
+import org.apache.sling.feature.io.json.FeatureJSONWriter;
+import org.apache.sling.feature.io.json.FeatureJSONReader.SubstituteVariables;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 
 import java.io.IOException;
diff --git a/src/main/java/org/apache/sling/feature/maven/mojos/AttachFeature.java b/src/main/java/org/apache/sling/feature/maven/mojos/AttachFeature.java
index 79c5c23..2cf38ff 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/AttachFeature.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/AttachFeature.java
@@ -22,9 +22,9 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.io.json.FeatureJSONWriter;
 import org.apache.sling.feature.maven.FeatureConstants;
 import org.apache.sling.feature.maven.ProjectHelper;
-import org.apache.sling.feature.support.json.FeatureJSONWriter;
 
 import java.io.File;
 import java.io.FileWriter;

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 03/14: Refactor start order handling

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit acde4efe4e8e54fb5407c543d12564eca9bcad7b
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Fri Jan 19 08:07:53 2018 +0100

    Refactor start order handling
---
 src/main/java/org/apache/sling/feature/maven/Preprocessor.java | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index f7c011d..1435e4b 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -23,7 +23,6 @@ import java.io.Reader;
 import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.stream.Collectors;
 
 import org.apache.maven.model.Dependency;
@@ -296,8 +295,8 @@ public class Preprocessor {
             final ProjectInfo info,
             final Feature assembledFeature,
             final String scope) {
-        for(final Map.Entry<Integer, org.apache.sling.feature.Artifact> entry : assembledFeature.getBundles().getAllBundles()) {
-            final ArtifactId a = entry.getValue().getId();
+        for(final org.apache.sling.feature.Artifact entry : assembledFeature.getBundles()) {
+            final ArtifactId a = entry.getId();
             if ( a.getGroupId().equals(info.project.getGroupId())
                  && a.getArtifactId().equals(info.project.getArtifactId())
                  && a.getVersion().equals(info.project.getVersion()) ) {

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 06/14: Support variables in converting from features to provisioning model

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit a1e954126b5f92a4a6e6df68c68bbe3ccdc31dd3
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Tue Mar 20 10:46:52 2018 +0000

    Support variables in converting from features to provisioning model
---
 src/main/java/org/apache/sling/feature/maven/Preprocessor.java | 10 +++++-----
 .../java/org/apache/sling/feature/maven/ProjectHelper.java     |  6 +++---
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index 3799712..4e2f08b 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -28,7 +28,7 @@ import org.apache.sling.feature.process.FeatureBuilder;
 import org.apache.sling.feature.process.FeatureProvider;
 import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.json.FeatureJSONReader;
-import org.apache.sling.feature.support.json.FeatureJSONReader.Phase;
+import org.apache.sling.feature.support.json.FeatureJSONReader.SubstituteVariables;
 import org.codehaus.plexus.logging.Logger;
 
 import java.io.File;
@@ -194,7 +194,7 @@ public class Preprocessor {
 
                 // We should pass in an "id" to FeatureJSONReader.read and later on check the id (again, need to handle ref files)
                 try (final FileReader reader = new FileReader(file)) {
-                    final Feature feature = FeatureJSONReader.read(reader, id, file.getAbsolutePath(), Phase.RESOLVE);
+                    final Feature feature = FeatureJSONReader.read(reader, id, file.getAbsolutePath(), SubstituteVariables.RESOLVE);
 
                     this.checkFeatureId(id, feature);
 
@@ -369,7 +369,7 @@ public class Preprocessor {
         if ( config.getInlinedFeature() != null ) {
             logger.debug("Reading inlined model from project " + project.getId());
             try (final Reader reader = new StringReader(config.getInlinedFeature())) {
-                feature = FeatureJSONReader.read(reader, id, null, Phase.RESOLVE);
+                feature = FeatureJSONReader.read(reader, id, null, SubstituteVariables.RESOLVE);
             } catch ( final IOException io) {
                 throw new RuntimeException("Unable to read inlined feature", io);
             }
@@ -380,7 +380,7 @@ public class Preprocessor {
             }
             logger.debug("Reading feature " + featureFile + " in project " + project.getId());
             try (final FileReader reader = new FileReader(featureFile)) {
-                feature = FeatureJSONReader.read(reader, id, featureFile.getAbsolutePath(), Phase.RESOLVE);
+                feature = FeatureJSONReader.read(reader, id, featureFile.getAbsolutePath(), SubstituteVariables.RESOLVE);
             } catch ( final IOException io) {
                 throw new RuntimeException("Unable to read feature " + featureFile, io);
             }
@@ -503,7 +503,7 @@ public class Preprocessor {
                     // "external" dependency, we can already resolve it
                     final File featureFile = ProjectHelper.getOrResolveArtifact(info.project, env.session, env.artifactHandlerManager, env.resolver, id).getFile();
                     try (final FileReader r = new FileReader(featureFile)) {
-                        return FeatureJSONReader.read(r, featureFile.getAbsolutePath(), Phase.RESOLVE);
+                        return FeatureJSONReader.read(r, featureFile.getAbsolutePath(), SubstituteVariables.RESOLVE);
                     } catch ( final IOException ioe) {
                         env.logger.error("Unable to read feature file from " + featureFile, ioe);
                     }
diff --git a/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
index 2efb69c..ce3314c 100644
--- a/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
+++ b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
@@ -31,7 +31,7 @@ import org.apache.maven.project.MavenProject;
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.support.json.FeatureJSONReader;
-import org.apache.sling.feature.support.json.FeatureJSONReader.Phase;
+import org.apache.sling.feature.support.json.FeatureJSONReader.SubstituteVariables;
 import org.apache.sling.feature.support.json.FeatureJSONWriter;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 
@@ -96,7 +96,7 @@ public abstract class ProjectHelper {
                 result = null;
             } else {
                 try ( final StringReader r = new StringReader(text) ) {
-                    result = FeatureJSONReader.read(r, project.getId(), Phase.RESOLVE);
+                    result = FeatureJSONReader.read(r, project.getId(), SubstituteVariables.RESOLVE);
                     project.setContextValue(cacheKey, result);
                 } catch ( final IOException ioe) {
                     throw new RuntimeException(ioe.getMessage(), ioe);
@@ -125,7 +125,7 @@ public abstract class ProjectHelper {
                         throw new RuntimeException("Unable to get feature from internal store.");
                     }
                     try ( final StringReader r = new StringReader(text) ) {
-                        final Feature feature = FeatureJSONReader.read(r, project.getId(), Phase.RESOLVE);
+                        final Feature feature = FeatureJSONReader.read(r, project.getId(), SubstituteVariables.RESOLVE);
                         result.add(feature);
                     } catch ( final IOException ioe) {
                         throw new RuntimeException(ioe.getMessage(), ioe);

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 10/14: Rename to FileUtils and use constants

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 0327076cc145c5fd2173302bb3596fca0d16c2d4
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed Apr 18 09:55:21 2018 +0200

    Rename to FileUtils and use constants
---
 src/main/java/org/apache/sling/feature/maven/Preprocessor.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index 9d7f6b6..a2665f8 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -235,7 +235,7 @@ public class Preprocessor {
 
             for(final File file : files) {
                 try {
-                    final List<String> features = org.apache.sling.feature.support.io.FeatureUtil.parseFeatureRefFile(file);
+                    final List<String> features = org.apache.sling.feature.support.io.FileUtils.parseFeatureRefFile(file);
                     if ( features.isEmpty() ) {
                         env.logger.debug("Empty feature ref file at " + file);
                     } else {

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 12/14: [Sling Feature Model] Split off IO packages into separate module.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 47ef2e473077913964201211a6d04ccef28669c4
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Wed Apr 25 10:58:43 2018 +0100

    [Sling Feature Model] Split off IO packages into separate module.
---
 pom.xml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/pom.xml b/pom.xml
index 3235f5d..ec05534 100644
--- a/pom.xml
+++ b/pom.xml
@@ -115,6 +115,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature.io</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature.support</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 05/14: [Feature Model] Support separate phases for reading variables

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 420177661c9619f65e4d94404f3e0be13eb6b8b3
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Fri Mar 16 12:01:14 2018 +0000

    [Feature Model] Support separate phases for reading variables
    
    Variables in the feature model must be substituted at different points in
    time, depending on where they reside. Variables in the includes, bundle,
    requirements and capabilities section must be substituted before the
    resolver runs, as they influence the resolver result. They should not be
    substituted at launch time. Other variables, such as configuration and
    framework properties variables must be substituted at launch time.
---
 .../apache/sling/feature/maven/Preprocessor.java   | 27 +++++++++++-----------
 .../apache/sling/feature/maven/ProjectHelper.java  |  5 ++--
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index 1435e4b..3799712 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -16,15 +16,6 @@
  */
 package org.apache.sling.feature.maven;
 
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
 import org.apache.maven.model.Dependency;
 import org.apache.maven.project.MavenProject;
 import org.apache.sling.feature.Artifact;
@@ -37,8 +28,18 @@ import org.apache.sling.feature.process.FeatureBuilder;
 import org.apache.sling.feature.process.FeatureProvider;
 import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.json.FeatureJSONReader;
+import org.apache.sling.feature.support.json.FeatureJSONReader.Phase;
 import org.codehaus.plexus.logging.Logger;
 
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
 /**
  * The processor processes all feature projects.
  */
@@ -193,7 +194,7 @@ public class Preprocessor {
 
                 // We should pass in an "id" to FeatureJSONReader.read and later on check the id (again, need to handle ref files)
                 try (final FileReader reader = new FileReader(file)) {
-                    final Feature feature = FeatureJSONReader.read(reader, id, file.getAbsolutePath());
+                    final Feature feature = FeatureJSONReader.read(reader, id, file.getAbsolutePath(), Phase.RESOLVE);
 
                     this.checkFeatureId(id, feature);
 
@@ -368,7 +369,7 @@ public class Preprocessor {
         if ( config.getInlinedFeature() != null ) {
             logger.debug("Reading inlined model from project " + project.getId());
             try (final Reader reader = new StringReader(config.getInlinedFeature())) {
-                feature = FeatureJSONReader.read(reader, id, null);
+                feature = FeatureJSONReader.read(reader, id, null, Phase.RESOLVE);
             } catch ( final IOException io) {
                 throw new RuntimeException("Unable to read inlined feature", io);
             }
@@ -379,7 +380,7 @@ public class Preprocessor {
             }
             logger.debug("Reading feature " + featureFile + " in project " + project.getId());
             try (final FileReader reader = new FileReader(featureFile)) {
-                feature = FeatureJSONReader.read(reader, id, featureFile.getAbsolutePath());
+                feature = FeatureJSONReader.read(reader, id, featureFile.getAbsolutePath(), Phase.RESOLVE);
             } catch ( final IOException io) {
                 throw new RuntimeException("Unable to read feature " + featureFile, io);
             }
@@ -502,7 +503,7 @@ public class Preprocessor {
                     // "external" dependency, we can already resolve it
                     final File featureFile = ProjectHelper.getOrResolveArtifact(info.project, env.session, env.artifactHandlerManager, env.resolver, id).getFile();
                     try (final FileReader r = new FileReader(featureFile)) {
-                        return FeatureJSONReader.read(r, featureFile.getAbsolutePath());
+                        return FeatureJSONReader.read(r, featureFile.getAbsolutePath(), Phase.RESOLVE);
                     } catch ( final IOException ioe) {
                         env.logger.error("Unable to read feature file from " + featureFile, ioe);
                     }
diff --git a/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
index a314113..2efb69c 100644
--- a/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
+++ b/src/main/java/org/apache/sling/feature/maven/ProjectHelper.java
@@ -31,6 +31,7 @@ import org.apache.maven.project.MavenProject;
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.support.json.FeatureJSONReader;
+import org.apache.sling.feature.support.json.FeatureJSONReader.Phase;
 import org.apache.sling.feature.support.json.FeatureJSONWriter;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 
@@ -95,7 +96,7 @@ public abstract class ProjectHelper {
                 result = null;
             } else {
                 try ( final StringReader r = new StringReader(text) ) {
-                    result = FeatureJSONReader.read(r, project.getId());
+                    result = FeatureJSONReader.read(r, project.getId(), Phase.RESOLVE);
                     project.setContextValue(cacheKey, result);
                 } catch ( final IOException ioe) {
                     throw new RuntimeException(ioe.getMessage(), ioe);
@@ -124,7 +125,7 @@ public abstract class ProjectHelper {
                         throw new RuntimeException("Unable to get feature from internal store.");
                     }
                     try ( final StringReader r = new StringReader(text) ) {
-                        final Feature feature = FeatureJSONReader.read(r, project.getId());
+                        final Feature feature = FeatureJSONReader.read(r, project.getId(), Phase.RESOLVE);
                         result.add(feature);
                     } catch ( final IOException ioe) {
                         throw new RuntimeException(ioe.getMessage(), ioe);

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 04/14: Update to parent pom 33

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit b70cc2996c5558c0404fcb272d8b7924d83d139e
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Mon Feb 26 13:24:32 2018 +0100

    Update to parent pom 33
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 0d887cf..3235f5d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
-        <version>32</version>
+        <version>33</version>
         <relativePath />
     </parent>
 

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-slingfeature-maven-plugin] 02/14: Start changing start level handling to start order handling

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git

commit 0b61a69f0d170a7da1d59ceeb1fc1afb3b2f520a
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Thu Jan 18 16:14:50 2018 +0100

    Start changing start level handling to start order handling
---
 .../apache/sling/feature/maven/Preprocessor.java   | 25 +++++++++++-----------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
index 47a09c5..f7c011d 100644
--- a/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
+++ b/src/main/java/org/apache/sling/feature/maven/Preprocessor.java
@@ -16,6 +16,16 @@
  */
 package org.apache.sling.feature.maven;
 
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
 import org.apache.maven.model.Dependency;
 import org.apache.maven.project.MavenProject;
 import org.apache.sling.feature.Artifact;
@@ -30,16 +40,6 @@ import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.json.FeatureJSONReader;
 import org.codehaus.plexus.logging.Logger;
 
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
 /**
  * The processor processes all feature projects.
  */
@@ -116,7 +116,8 @@ public class Preprocessor {
                         info.project.getVersion(),
                         null,
                         "jar"));
-                feature.getBundles().add(Integer.valueOf(config.getJarStartLevel()), jar);
+                jar.getMetadata().put(Artifact.KEY_START_ORDER, String.valueOf(config.getJarStartLevel()));
+                feature.getBundles().add(jar);
             }
         }
 
@@ -295,7 +296,7 @@ public class Preprocessor {
             final ProjectInfo info,
             final Feature assembledFeature,
             final String scope) {
-        for(final Map.Entry<Integer, org.apache.sling.feature.Artifact> entry : assembledFeature.getBundles()) {
+        for(final Map.Entry<Integer, org.apache.sling.feature.Artifact> entry : assembledFeature.getBundles().getAllBundles()) {
             final ArtifactId a = entry.getValue().getId();
             if ( a.getGroupId().equals(info.project.getGroupId())
                  && a.getArtifactId().equals(info.project.getArtifactId())

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.