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

rombert pushed a commit to annotated tag maven-launchpad-plugin-2.0.10
in repository 
https://gitbox.apache.org/repos/asf/sling-maven-launchpad-plugin.git

commit 5682b2d1d34800af0835d1831dbe9ad301421fa8
Author: Justin Edelson <[email protected]>
AuthorDate: Wed Feb 3 19:08:36 2010 +0000

    Unifying bundle addition / removal code (re: SLING-1321)
    
    git-svn-id: 
https://svn.apache.org/repos/asf/sling/trunk/maven/maven-launchpad-plugin@906180
 13f79535-47bb-0310-9956-ffa450edef68
---
 .../projectsupport/AbstractBundleListMojo.java     | 332 ++++++++-------------
 .../AbstractLaunchpadFrameworkMojo.java            |  76 +++++
 .../maven/projectsupport/ArtifactDefinition.java   |  21 +-
 .../maven/projectsupport/AttachBundleListMojo.java |  42 ++-
 .../CheckBundleListForSnapshotsMojo.java           |  60 ++--
 .../maven/projectsupport/CreateBundleJarMojo.java  |  14 +-
 .../CreateKarafFeatureDescriptorMojo.java          | 188 ++++--------
 .../maven/projectsupport/PreparePackageMojo.java   | 140 ++++-----
 .../projectsupport/bundlelist/BaseBundle.java      |  33 ++
 .../projectsupport/bundlelist/BaseBundleList.java  |  92 ++++++
 .../projectsupport/bundlelist/BaseStartLevel.java  |  60 ++++
 src/main/mdo/bundle-list.xml                       |   3 +
 .../projectsupport/PreparePackageMojoTest.java     |   4 +-
 13 files changed, 589 insertions(+), 476 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/AbstractBundleListMojo.java
 
b/src/main/java/org/apache/sling/maven/projectsupport/AbstractBundleListMojo.java
index 8aa3ae8..0c2fe4c 100644
--- 
a/src/main/java/org/apache/sling/maven/projectsupport/AbstractBundleListMojo.java
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/AbstractBundleListMojo.java
@@ -35,75 +35,72 @@ import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.MavenProjectHelper;
-import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
 import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
-import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.StartLevel;
 import 
org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.io.xpp3.BundleListXpp3Reader;
-import org.codehaus.plexus.archiver.ArchiverException;
-import org.codehaus.plexus.archiver.UnArchiver;
-import org.codehaus.plexus.archiver.manager.ArchiverManager;
-import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
-import 
org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector;
-import org.codehaus.plexus.util.FileUtils;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
 public abstract class AbstractBundleListMojo extends AbstractMojo {
 
     /**
-     * The name of the directory within the output directory into which the 
base
-     * JAR should be installed.
-     *
-     * @parameter default-value="resources"
+     * JAR Packaging type.
      */
-    protected String baseDestination;
+    protected static final String JAR = "jar";
 
     /**
-     * The directory which contains the start-level bundle directories.
-     *
-     * @parameter default-value="bundles"
+     * WAR Packaging type.
      */
-    protected String bundlesDirectory;
+    protected static final String WAR = "war";
+
+    protected static boolean shouldCopy(File source, File dest) {
+        if (!dest.exists()) {
+            return true;
+        } else {
+            return source.lastModified() > dest.lastModified();
+        }
+    }
 
     /**
-     * The definition of the defaultBundleList artifact.
-     *
-     * @parameter
+     * @parameter default-value="${basedir}/src/main/bundles/list.xml"
      */
-    private ArtifactDefinition defaultBundleList;
+    protected File bundleListFile;
 
     /**
-     * The definition of the defaultBundles package.
+     * The definition of the defaultBundleList artifact.
      *
      * @parameter
      */
-    private ArtifactDefinition defaultBundles;
+    protected ArtifactDefinition defaultBundleList;
 
     /**
-     * @parameter default-value="${basedir}/src/main/bundles/list.xml"
+     * The Maven project.
+     *
+     * @parameter expression="${project}"
+     * @required
+     * @readonly
      */
-    protected File bundleListFile;
+    protected MavenProject project;
 
     /**
-     * To look up Archiver/UnArchiver implementations
-     *
      * @component
      */
-    private ArchiverManager archiverManager;
+    protected MavenProjectHelper projectHelper;
 
     /**
-     * @component
+     * Any additional bundles to include in the project's bundles directory.
+     *
+     * @parameter
      */
-    protected MavenProjectHelper projectHelper;
+    private ArtifactDefinition[] additionalBundles;
+
+    private BundleList bundleList;
 
     /**
-     * The Maven project.
+     * Bundles which should be removed from the project's bundles directory.
      *
-     * @parameter expression="${project}"
-     * @required
-     * @readonly
+     * @parameter
      */
-    protected MavenProject project;
+    private ArtifactDefinition[] bundleExclusions;
 
     /**
      * Used to look up Artifacts in the remote repository.
@@ -113,6 +110,13 @@ public abstract class AbstractBundleListMojo extends 
AbstractMojo {
     private ArtifactFactory factory;
 
     /**
+     * If true, include the default bundles.
+     *
+     * @parameter default-value="true"
+     */
+    private boolean includeDefaultBundles;
+
+    /**
      * Location of the local repository.
      *
      * @parameter expression="${localRepository}"
@@ -122,16 +126,6 @@ public abstract class AbstractBundleListMojo extends 
AbstractMojo {
     private ArtifactRepository local;
 
     /**
-     * JAR Packaging type.
-     */
-    protected static final String JAR = "jar";
-
-    /**
-     * WAR Packaging type.
-     */
-    protected static final String WAR = "war";
-
-    /**
      * List of Remote Repositories used by the resolver.
      *
      * @parameter expression="${project.remoteArtifactRepositories}"
@@ -147,31 +141,41 @@ public abstract class AbstractBundleListMojo extends 
AbstractMojo {
      */
     private ArtifactResolver resolver;
 
-    public final void execute() throws MojoFailureException,
-            MojoExecutionException {
+    public final void execute() throws MojoFailureException, 
MojoExecutionException {
         try {
-            initArtifactDefinitions();
-        } catch (IOException e) {
-            throw new MojoExecutionException(
-                    "Unable to load dependency information from properties 
file.",
-                    e);
+            initBundleList();
+        } catch (Exception e) {
+            throw new MojoExecutionException("Unable to load dependency 
information from properties file.", e);
         }
         executeWithArtifacts();
 
     }
 
-    protected abstract void executeWithArtifacts()
-            throws MojoExecutionException, MojoFailureException;
+    /**
+     * Execute the logic of the plugin after the default artifacts have been
+     * initialized.
+     */
+    protected abstract void executeWithArtifacts() throws 
MojoExecutionException, MojoFailureException;
 
-    protected Artifact getArtifact(ArtifactDefinition bundle)
-            throws MojoExecutionException {
-        return getArtifact(bundle.getGroupId(), bundle.getArtifactId(), bundle
-                .getVersion(), bundle.getType() != null ? bundle.getType()
-                : JAR, bundle.getClassifier());
+    /**
+     * Get a resolved Artifact from the coordinates found in the artifact
+     * definition.
+     *
+     * @param def the artifact definition
+     * @return the artifact, which has been resolved
+     * @throws MojoExecutionException
+     */
+    protected Artifact getArtifact(ArtifactDefinition def) throws 
MojoExecutionException {
+        return getArtifact(def.getGroupId(), def.getArtifactId(), 
def.getVersion(), def.getType(), def.getClassifier());
     }
 
-    protected Artifact getArtifact(String groupId, String artifactId,
-            String version, String type, String classifier)
+    /**
+     * Get a resolved Artifact from the coordinates provided
+     *
+     * @return the artifact, which has been resolved.
+     * @throws MojoExecutionException
+     */
+    protected Artifact getArtifact(String groupId, String artifactId, String 
version, String type, String classifier)
             throws MojoExecutionException {
         Artifact artifact;
         VersionRange vr;
@@ -183,11 +187,10 @@ public abstract class AbstractBundleListMojo extends 
AbstractMojo {
         }
 
         if (StringUtils.isEmpty(classifier)) {
-            artifact = factory.createDependencyArtifact(groupId, artifactId,
-                    vr, type, null, Artifact.SCOPE_COMPILE);
+            artifact = factory.createDependencyArtifact(groupId, artifactId, 
vr, type, null, Artifact.SCOPE_COMPILE);
         } else {
-            artifact = factory.createDependencyArtifact(groupId, artifactId,
-                    vr, type, classifier, Artifact.SCOPE_COMPILE);
+            artifact = factory.createDependencyArtifact(groupId, artifactId, 
vr, type, classifier,
+                    Artifact.SCOPE_COMPILE);
         }
         try {
             resolver.resolve(artifact, remoteRepos, local);
@@ -199,127 +202,80 @@ public abstract class AbstractBundleListMojo extends 
AbstractMojo {
         return artifact;
     }
 
-    protected final void initArtifactDefinitions() throws IOException {
-        Properties dependencies = new Properties();
-        dependencies
-                .load(getClass()
-                        .getResourceAsStream(
-                                
"/org/apache/sling/maven/projectsupport/dependencies.properties"));
-
-        if (defaultBundles == null) {
-            defaultBundles = new ArtifactDefinition();
-        }
-        
defaultBundles.initDefaults(dependencies.getProperty("defaultBundles"));
-
-        if (defaultBundleList == null) {
-            defaultBundleList = new ArtifactDefinition();
-        }
-        
defaultBundleList.initDefaults(dependencies.getProperty("defaultBundleList"));
-
-        initArtifactDefinitions(dependencies);
+    protected BundleList getBundleList() {
+        return bundleList;
     }
 
+    /**
+     * Hook methods for subclasses to initialize any additional artifact
+     * definitions.
+     *
+     * @param dependencies the dependency properties loaded from the JAR file
+     */
     protected void initArtifactDefinitions(Properties dependencies) {
     }
 
-    protected void copy(ArtifactDefinition additionalBundle,
-            File outputDirectory) throws MojoExecutionException {
-        Artifact artifact = getArtifact(additionalBundle);
-        copy(artifact.getFile(), additionalBundle.getStartLevel(),
-                outputDirectory);
+    /**
+     * Hook methods for subclasses to initialize the bundle list.
+     */
+    protected void initBundleList(BundleList bundleList) {
     }
 
-    protected void copy(File file, int startLevel, File outputDirectory)
-            throws MojoExecutionException {
-        File destination = new File(outputDirectory, String.format(
-                "%s/%s/%s/%s", baseDestination, bundlesDirectory, startLevel,
-                file.getName()));
-        if (shouldCopy(file, destination)) {
-            getLog().info(
-                    String.format("Copying bundle from %s to %s", file
-                            .getPath(), destination.getPath()));
-            try {
-                FileUtils.copyFile(file, destination);
-            } catch (IOException e) {
-                throw new MojoExecutionException("Unable to copy bundle from "
-                        + file.getPath(), e);
-            }
-        }
+    protected boolean isCurrentArtifact(ArtifactDefinition def) {
+        return (def.getGroupId().equals(project.getGroupId()) && 
def.getArtifactId().equals(project.getArtifactId()));
     }
 
+    /**
+     * Initialize the artifact definitions using defaults inside the plugin 
JAR.
+     *
+     * @throws IOException if the default properties can't be read
+     * @throws XmlPullParserException
+     * @throws MojoExecutionException
+     */
+    private final void initArtifactDefinitions() throws IOException {
+        Properties dependencies = new Properties();
+        dependencies.load(getClass().getResourceAsStream(
+                
"/org/apache/sling/maven/projectsupport/dependencies.properties"));
 
-    protected BundleList readBundleList() throws IOException, 
XmlPullParserException {
-        return readBundleList(bundleListFile);
-    }
+        if (defaultBundleList == null) {
+            defaultBundleList = new ArtifactDefinition();
+        }
+        
defaultBundleList.initDefaults(dependencies.getProperty("defaultBundleList"));
 
+        initArtifactDefinitions(dependencies);
+    }
 
-    protected void outputBundleList(File outputDirectory)
-            throws MojoExecutionException {
-        try {
-            if (bundleListFile != null && bundleListFile.exists()) {
-                getLog().info(
-                        "Using bundle list file from "
-                                + bundleListFile.getAbsolutePath());
-                BundleList bundles = readBundleList(bundleListFile);
-                copyBundles(bundles, outputDirectory);
-                return;
+    private final void initBundleList() throws IOException, 
XmlPullParserException, MojoExecutionException {
+        initArtifactDefinitions();
+        if (isCurrentArtifact(defaultBundleList)) {
+            bundleList = readBundleList(bundleListFile);
+        } else {
+            bundleList = new BundleList();
+            if (includeDefaultBundles) {
+                Artifact artifact = 
getArtifact(defaultBundleList.getGroupId(), defaultBundleList.getArtifactId(),
+                        defaultBundleList.getVersion(), 
defaultBundleList.getType(), defaultBundleList.getClassifier());
+                getLog().info("Using bundle list file from " + 
artifact.getFile().getAbsolutePath());
+                bundleList = readBundleList(artifact.getFile());
             }
-        } catch (Exception e) {
-            getLog()
-                    .warn(
-                            String
-                                    .format(
-                                            "Unable to use bundle list from 
%s. Falling back to bundles artifact.",
-                                            bundleListFile), e);
-        }
 
-        if (!isCurrentArtifact(defaultBundleList)) {
-            try {
-                Artifact artifact = getArtifact(defaultBundleList.getGroupId(),
-                        defaultBundleList.getArtifactId(), defaultBundleList
-                                .getVersion(), defaultBundleList.getType(),
-                        defaultBundleList.getClassifier());
-                getLog().info(
-                        "Using bundle list file from "
-                                + artifact.getFile().getAbsolutePath());
-                BundleList bundles = readBundleList(artifact.getFile());
-                copyBundles(bundles, outputDirectory);
-                return;
-            } catch (Exception e) {
-                getLog()
-                        .warn(
-                                "Unable to load bundle list from artifact. 
Falling back to bundle jar",
-                                e);
+            if (bundleListFile.exists()) {
+                bundleList.merge(readBundleList(bundleListFile));
             }
         }
-
-        if (!isCurrentArtifact(defaultBundleList)) {
-            Artifact defaultBundlesArtifact = getArtifact(defaultBundles
-                    .getGroupId(), defaultBundles.getArtifactId(),
-                    defaultBundles.getVersion(), defaultBundles.getType(),
-                    defaultBundles.getClassifier());
-            unpack(defaultBundlesArtifact.getFile(), outputDirectory, null,
-                    "META-INF/**");
+        if (additionalBundles != null) {
+            for (ArtifactDefinition def : additionalBundles) {
+                bundleList.add(def.toBundle());
+            }
         }
-    }
-
-    private boolean isCurrentArtifact(ArtifactDefinition def) {
-        return (def.getGroupId().equals(project.getGroupId()) && def
-                .getArtifactId().equals(project.getArtifactId()));
-    }
-
-    private void copyBundles(BundleList bundles, File outputDirectory)
-            throws MojoExecutionException {
-        for (StartLevel startLevel : bundles.getStartLevels()) {
-            for (Bundle bundle : startLevel.getBundles()) {
-                copy(new ArtifactDefinition(bundle, startLevel.getLevel()),
-                        outputDirectory);
+        if (bundleExclusions != null) {
+            for (ArtifactDefinition def : bundleExclusions) {
+                bundleList.remove(def.toBundle(), false);
             }
         }
+        initBundleList(bundleList);
     }
 
-    protected BundleList readBundleList(File file) throws IOException,
-            XmlPullParserException {
+    private BundleList readBundleList(File file) throws IOException, 
XmlPullParserException {
         BundleListXpp3Reader reader = new BundleListXpp3Reader();
         FileInputStream fis = new FileInputStream(file);
         try {
@@ -329,50 +285,4 @@ public abstract class AbstractBundleListMojo extends 
AbstractMojo {
         }
     }
 
-    protected boolean shouldCopy(File source, File dest) {
-        if (!dest.exists()) {
-            return true;
-        } else {
-            return source.lastModified() > dest.lastModified();
-        }
-    }
-
-    protected void unpack(File source, File destination, String includes,
-            String excludes) throws MojoExecutionException {
-        getLog().info(
-                "Unpacking " + source.getPath() + " to\n  "
-                        + destination.getPath());
-        try {
-            destination.mkdirs();
-
-            UnArchiver unArchiver = archiverManager.getUnArchiver(source);
-
-            unArchiver.setSourceFile(source);
-            unArchiver.setDestDirectory(destination);
-
-            if (StringUtils.isNotEmpty(excludes)
-                    || StringUtils.isNotEmpty(includes)) {
-                IncludeExcludeFileSelector[] selectors = new 
IncludeExcludeFileSelector[] { new IncludeExcludeFileSelector() };
-
-                if (StringUtils.isNotEmpty(excludes)) {
-                    selectors[0].setExcludes(excludes.split(","));
-                }
-
-                if (StringUtils.isNotEmpty(includes)) {
-                    selectors[0].setIncludes(includes.split(","));
-                }
-
-                unArchiver.setFileSelectors(selectors);
-            }
-
-            unArchiver.extract();
-        } catch (NoSuchArchiverException e) {
-            throw new MojoExecutionException("Unable to find archiver for "
-                    + source.getPath(), e);
-        } catch (ArchiverException e) {
-            throw new MojoExecutionException("Unable to unpack "
-                    + source.getPath(), e);
-        }
-    }
-
 }
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/AbstractLaunchpadFrameworkMojo.java
 
b/src/main/java/org/apache/sling/maven/projectsupport/AbstractLaunchpadFrameworkMojo.java
new file mode 100644
index 0000000..7eeede7
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/AbstractLaunchpadFrameworkMojo.java
@@ -0,0 +1,76 @@
+/*
+ * 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.maven.projectsupport;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.StartLevel;
+import org.codehaus.plexus.util.FileUtils;
+
+/**
+ * This class contains the Launchpad-framework specific utility methods.
+ *
+ */
+public abstract class AbstractLaunchpadFrameworkMojo extends 
AbstractBundleListMojo {
+
+    /**
+     * The name of the directory within the output directory into which the 
base
+     * JAR should be installed.
+     *
+     * @parameter default-value="resources"
+     */
+    protected String baseDestination;
+
+    /**
+     * The directory which contains the start-level bundle directories.
+     *
+     * @parameter default-value="bundles"
+     */
+    protected String bundlesDirectory;
+
+    protected void copyBundles(BundleList bundles, File outputDirectory) 
throws MojoExecutionException {
+        for (StartLevel startLevel : bundles.getStartLevels()) {
+            for (Bundle bundle : startLevel.getBundles()) {
+                copy(new ArtifactDefinition(bundle, startLevel.getLevel()), 
outputDirectory);
+            }
+        }
+    }
+
+    protected void copy(ArtifactDefinition additionalBundle, File 
outputDirectory) throws MojoExecutionException {
+        Artifact artifact = getArtifact(additionalBundle);
+        copy(artifact.getFile(), additionalBundle.getStartLevel(), 
outputDirectory);
+    }
+
+    protected void copy(File file, int startLevel, File outputDirectory) 
throws MojoExecutionException {
+        File destination = new File(outputDirectory, 
String.format("%s/%s/%s/%s", baseDestination, bundlesDirectory,
+                startLevel, file.getName()));
+        if (shouldCopy(file, destination)) {
+            getLog().info(String.format("Copying bundle from %s to %s", 
file.getPath(), destination.getPath()));
+            try {
+                FileUtils.copyFile(file, destination);
+            } catch (IOException e) {
+                throw new MojoExecutionException("Unable to copy bundle from " 
+ file.getPath(), e);
+            }
+        }
+    }
+
+}
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/ArtifactDefinition.java 
b/src/main/java/org/apache/sling/maven/projectsupport/ArtifactDefinition.java
index 1c89034..801b879 100644
--- 
a/src/main/java/org/apache/sling/maven/projectsupport/ArtifactDefinition.java
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/ArtifactDefinition.java
@@ -41,7 +41,7 @@ public class ArtifactDefinition {
 
     /** The artifact version */
     private String version;
-    
+
     public ArtifactDefinition() {
     }
 
@@ -113,10 +113,10 @@ public class ArtifactDefinition {
      * Initialize this ArtifactDefinition with a set of default values from a
      * comma-delimited string. This string must have 6 items in it:
      * [groupId],[artifactId],[version],[type],[classifier],[startLevel]
-     * 
+     *
      * The only required parameter is the last one, which must be parseable as
      * an integer.
-     * 
+     *
      * @param commaDelimitedList
      *            the comma-delimited list
      */
@@ -137,7 +137,7 @@ public class ArtifactDefinition {
      * Initialize this ArtifactDefinition with a set of default values. If the
      * corresponding field in this object is null (or 0 in the case of start
      * level) and the parameter is non-null, the parameter value will be used.
-     * 
+     *
      * @param groupId
      *            the groupId
      * @param artifactId
@@ -173,4 +173,17 @@ public class ArtifactDefinition {
         }
     }
 
+    public Bundle toBundle() {
+        Bundle bnd = new Bundle();
+        bnd.setArtifactId(artifactId);
+        bnd.setGroupId(groupId);
+        bnd.setVersion(version);
+        if (type != null) {
+            bnd.setType(type);
+        }
+        bnd.setClassifier(classifier);
+        bnd.setStartLevel(startLevel);
+        return bnd;
+    }
+
 }
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/AttachBundleListMojo.java 
b/src/main/java/org/apache/sling/maven/projectsupport/AttachBundleListMojo.java
index 13ede61..ddb0287 100644
--- 
a/src/main/java/org/apache/sling/maven/projectsupport/AttachBundleListMojo.java
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/AttachBundleListMojo.java
@@ -16,33 +16,51 @@
  */
 package org.apache.sling.maven.projectsupport;
 
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
+import 
org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.io.xpp3.BundleListXpp3Writer;
 
 /**
  * Attaches the bundle list as a project artifact.
- * 
+ *
  * @goal attach-bundle-list
  * @phase package
  * @description attach the bundle list as a project artifact
  */
 public class AttachBundleListMojo extends AbstractBundleListMojo {
-    
+
     private static final String CLASSIFIER = "bundlelist";
-    
+
     private static final String TYPE = "xml";
 
+    /**
+     * @parameter default-value="${project.build.directory}/bundleList.xml"
+     */
+    private File outputFile;
+
+    private BundleListXpp3Writer writer = new BundleListXpp3Writer();
+
     @Override
-    protected void executeWithArtifacts() throws MojoExecutionException,
-            MojoFailureException {
-        if (bundleListFile != null && bundleListFile.exists()) {
-            projectHelper.attachArtifact(project, TYPE, CLASSIFIER,
-                    bundleListFile);
-        } else {
-            throw new MojoExecutionException(
-                    "The bundle list file does not exist.");
+    protected void executeWithArtifacts() throws MojoExecutionException, 
MojoFailureException {
+        FileWriter fw = null;
+        try {
+            fw = new FileWriter(outputFile);
+            writer.write(fw, getBundleList());
+            projectHelper.attachArtifact(project, TYPE, CLASSIFIER, 
outputFile);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Unable to output effective 
bundle list", e);
+        } finally {
+            if (fw != null) {
+                try {
+                    fw.close();
+                } catch (IOException e) {
+                }
+            }
         }
-
     }
 
 }
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/CheckBundleListForSnapshotsMojo.java
 
b/src/main/java/org/apache/sling/maven/projectsupport/CheckBundleListForSnapshotsMojo.java
index 2982b93..cb0a210 100644
--- 
a/src/main/java/org/apache/sling/maven/projectsupport/CheckBundleListForSnapshotsMojo.java
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/CheckBundleListForSnapshotsMojo.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sling.maven.projectsupport;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -25,60 +24,45 @@ import org.apache.maven.plugin.MojoFailureException;
 import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
 import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
 import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.StartLevel;
-import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
 /**
  * Validate that the bundle list file (if it exists) does not contain 
references
  * to SNAPSHOT versions.
- * 
+ *
  * @goal check-bundle-list-for-snapshots
- * 
+ *
  */
 public class CheckBundleListForSnapshotsMojo extends AbstractBundleListMojo {
 
     /**
      * True if the build should be failed if a snapshot is found.
-     * 
+     *
      * @parameter default-value="true"
      */
     private boolean failOnSnapshot;
 
     @Override
-    protected void executeWithArtifacts() throws MojoExecutionException,
-            MojoFailureException {
-        if (bundleListFile.exists()) {
-            try {
-                List<Bundle> snapshots = new ArrayList<Bundle>();
-                BundleList bundleList = readBundleList();
-                for (StartLevel level : bundleList.getStartLevels()) {
-                    for (Bundle bundle : level.getBundles()) {
-                        if (isSnapshot(bundle)) {
-                            snapshots.add(bundle);
-                        }
-                    }
+    protected void executeWithArtifacts() throws MojoExecutionException, 
MojoFailureException {
+        List<Bundle> snapshots = new ArrayList<Bundle>();
+        BundleList bundleList = getBundleList();
+        for (StartLevel level : bundleList.getStartLevels()) {
+            for (Bundle bundle : level.getBundles()) {
+                if (isSnapshot(bundle)) {
+                    snapshots.add(bundle);
                 }
-                if (!snapshots.isEmpty()) {
-                    getLog()
-                            .error(
-                                    "The following entries in the bundle list 
file are SNAPSHOTs:");
-                    for (Bundle bundle : snapshots) {
-                        getLog().error(String.format("     %s:%s:%s", 
bundle.getGroupId(),
-                                bundle.getArtifactId(), bundle.getVersion()));
-                    }
-                    if (failOnSnapshot) {
-                        throw new MojoFailureException("SNAPSHOTs were found 
in the bundle list. See log.");
-                    }
-                }
-            } catch (IOException e) {
-                throw new MojoExecutionException(
-                        "Unable to load bundle list file", e);
-            } catch (XmlPullParserException e) {
-                throw new MojoExecutionException(
-                        "Unable to load bundle list file", e);
             }
-
-        } else {
-            getLog().debug("Bundle list file does not exist. Skipping.");
+        }
+        if (!snapshots.isEmpty()) {
+            getLog().error("The following entries in the bundle list file are 
SNAPSHOTs:");
+            for (Bundle bundle : snapshots) {
+                getLog().error(
+                        String
+                                .format("     %s:%s:%s", bundle.getGroupId(), 
bundle.getArtifactId(), bundle
+                                        .getVersion()));
+            }
+            if (failOnSnapshot) {
+                throw new MojoFailureException("SNAPSHOTs were found in the 
bundle list. See log.");
+            }
         }
     }
 
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/CreateBundleJarMojo.java 
b/src/main/java/org/apache/sling/maven/projectsupport/CreateBundleJarMojo.java
index 97b7747..01802db 100644
--- 
a/src/main/java/org/apache/sling/maven/projectsupport/CreateBundleJarMojo.java
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/CreateBundleJarMojo.java
@@ -29,7 +29,6 @@ import 
org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.StartLevel;
 import org.codehaus.plexus.archiver.ArchiverException;
 import org.codehaus.plexus.archiver.jar.JarArchiver;
 import org.codehaus.plexus.util.DirectoryScanner;
-import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
 /**
  * Create and attach a JAR file containing the resolved artifacts from the
@@ -40,7 +39,7 @@ import 
org.codehaus.plexus.util.xml.pull.XmlPullParserException;
  * @phase package
  *
  */
-public class CreateBundleJarMojo extends AbstractBundleListMojo {
+public class CreateBundleJarMojo extends AbstractLaunchpadFrameworkMojo {
 
        /**
         * The list of resources we want to add to the bundle JAR file.
@@ -76,16 +75,7 @@ public class CreateBundleJarMojo extends 
AbstractBundleListMojo {
        public static final String[] DEFAULT_INCLUDES = { "**/**" };
 
        private void addBundles() throws MojoExecutionException {
-               BundleList bundles = null;
-               try {
-                       bundles = readBundleList(bundleListFile);
-               } catch (IOException e) {
-                       throw new MojoExecutionException("Unable to read bundle 
list file",
-                                       e);
-               } catch (XmlPullParserException e) {
-                       throw new MojoExecutionException("Unable to read bundle 
list file",
-                                       e);
-               }
+               BundleList bundles = getBundleList();
 
                for (StartLevel level : bundles.getStartLevels()) {
                        for (Bundle bundle : level.getBundles()) {
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/CreateKarafFeatureDescriptorMojo.java
 
b/src/main/java/org/apache/sling/maven/projectsupport/CreateKarafFeatureDescriptorMojo.java
index f34382e..9e7e9e3 100644
--- 
a/src/main/java/org/apache/sling/maven/projectsupport/CreateKarafFeatureDescriptorMojo.java
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/CreateKarafFeatureDescriptorMojo.java
@@ -19,16 +19,12 @@ package org.apache.sling.maven.projectsupport;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
 
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
 import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
 import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.StartLevel;
-import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 import org.jdom.Document;
 import org.jdom.Element;
 import org.jdom.output.Format;
@@ -36,129 +32,77 @@ import org.jdom.output.XMLOutputter;
 
 /**
  * Create and attach a karaf feature descriptor XML file.
- * 
+ *
  * @goal create-karaf-descriptor
  * @phase package
  * @description create a karaf feature descriptor
  */
 public class CreateKarafFeatureDescriptorMojo extends AbstractBundleListMojo {
 
-       private static final String CLASSIFIER = "features";
-
-       private static final String TYPE = "xml";
-
-       /**
-        * @parameter
-        */
-       private String[] additionalBundles;
-
-       private Set<String> excludedArtifacts;
-       
-       /**
-        * @parameter
-        */
-       private String[] exclusions;
-       
-       /**
-        * @parameter default-value="sling"
-        */
-       private String featureName;
-       
-       /**
-        * @parameter default-value="sling-2.0"
-        */
-       private String featuresName;
-
-       /**
-        * @parameter default-value="${project.version}"
-        */
-       private String featureVersion;
-
-       /**
-        * The output directory.
-        * 
-        * @parameter default-value="${project.build.directory}"
-        */
-       private File outputDirectory;
-
-       @Override
-       protected void executeWithArtifacts() throws MojoExecutionException,
-                       MojoFailureException {
-               Document doc = new Document();
-
-               Element features = new Element("features");
-               doc.setRootElement(features);
-               features.setAttribute("name", featuresName);
-
-               Element feature = new Element("feature");
-               features.addContent(feature);
-               feature.setAttribute("name", featureName);
-               feature.setAttribute("version", featureVersion);
-               
-               excludedArtifacts = new HashSet<String>();
-               if (exclusions != null) {
-                       excludedArtifacts.addAll(Arrays.asList(exclusions));
-               }
-
-               try {
-                       BundleList bundleList = readBundleList();
-                       for (StartLevel level : bundleList.getStartLevels()) {
-                               for (Bundle bundle : level.getBundles()) {
-                                       if (include(bundle)) {
-                                               String bundleRef = 
String.format("mvn:%s/%s/%s", bundle
-                                                               .getGroupId(), 
bundle.getArtifactId(), bundle
-                                                               .getVersion());
-                                               feature.addContent(new 
Element("bundle")
-                                                               
.setText(bundleRef));
-                                       }
-                               }
-                       }
-               } catch (IOException e) {
-                       throw new MojoExecutionException("Unable to read bundle 
list file",
-                                       e);
-               } catch (XmlPullParserException e) {
-                       throw new MojoExecutionException("Unable to read bundle 
list file",
-                                       e);
-               }
-
-               if (additionalBundles != null) {
-                       for (String bundleRef : additionalBundles) {
-                               Element bundle = new Element("bundle");
-                               bundle.setText(bundleRef);
-                               feature.addContent(bundle);
-                       }
-               }
-
-               File outputFile = new File(outputDirectory, "features.xml");
-
-               FileOutputStream out = null;
-               try {
-                       out = new FileOutputStream(outputFile);
-                       new 
XMLOutputter(Format.getPrettyFormat().setEncoding("UTF-8"))
-                                       .output(doc, out);
-               } catch (IOException e) {
-                       throw new MojoExecutionException("Unable to write 
features.xml", e);
-               } finally {
-                       if (out != null) {
-                               try {
-                                       out.close();
-                               } catch (IOException e) {
-                               }
-                       }
-               }
-               projectHelper.attachArtifact(project, TYPE, CLASSIFIER, 
outputFile);
-
-       }
-
-       /**
-        * Decide if the bundle should be included in the bundle list.
-        * 
-        * @param bundle the bundle
-        * @return true if it should be included
-        */
-       private boolean include(Bundle bundle) {
-               String ref = bundle.getGroupId() + ":" + bundle.getArtifactId();
-               return !excludedArtifacts.contains(ref);
-       }
+    private static final String CLASSIFIER = "features";
+
+    private static final String TYPE = "xml";
+
+    /**
+     * @parameter default-value="sling"
+     */
+    private String featureName;
+
+    /**
+     * @parameter default-value="sling-2.0"
+     */
+    private String featuresName;
+
+    /**
+     * @parameter default-value="${project.version}"
+     */
+    private String featureVersion;
+
+    /**
+     * The output directory.
+     *
+     * @parameter default-value="${project.build.directory}/features.xml"
+     */
+    private File outputFile;
+
+    @Override
+    protected void executeWithArtifacts() throws MojoExecutionException, 
MojoFailureException {
+        Document doc = new Document();
+
+        Element features = new Element("features");
+        doc.setRootElement(features);
+        features.setAttribute("name", featuresName);
+
+        Element feature = new Element("feature");
+        features.addContent(feature);
+        feature.setAttribute("name", featureName);
+        feature.setAttribute("version", featureVersion);
+
+        BundleList bundleList = getBundleList();
+        for (StartLevel level : bundleList.getStartLevels()) {
+            for (Bundle bundle : level.getBundles()) {
+                String bundleRef = String.format("mvn:%s/%s/%s", 
bundle.getGroupId(), bundle.getArtifactId(), bundle
+                        .getVersion());
+                feature.addContent(new Element("bundle").setText(bundleRef));
+            }
+        }
+
+        FileOutputStream out = null;
+        try {
+            out = new FileOutputStream(outputFile);
+            new 
XMLOutputter(Format.getPrettyFormat().setEncoding("UTF-8")).output(doc, out);
+            projectHelper.attachArtifact(project, TYPE, CLASSIFIER, 
outputFile);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Unable to write features.xml", 
e);
+        } finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+
+    }
 
 }
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/PreparePackageMojo.java 
b/src/main/java/org/apache/sling/maven/projectsupport/PreparePackageMojo.java
index 262a6fa..5972e34 100644
--- 
a/src/main/java/org/apache/sling/maven/projectsupport/PreparePackageMojo.java
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/PreparePackageMojo.java
@@ -23,8 +23,14 @@ import java.util.Properties;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
-import org.codehaus.plexus.util.DirectoryScanner;
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.UnArchiver;
+import org.codehaus.plexus.archiver.manager.ArchiverManager;
+import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
+import 
org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector;
 import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.StringUtils;
 
 /**
  * Initialize a Sling application project by extracting bundles into the 
correct
@@ -35,28 +41,7 @@ import org.codehaus.plexus.util.FileUtils;
  * @phase process-sources
  * @description initialize a Sling application project
  */
-public class PreparePackageMojo extends AbstractBundleListMojo {
-
-       /**
-        * Any additional bundles to include in the project's bundles directory.
-        *
-        * @parameter
-        */
-       private ArtifactDefinition[] additionalBundles;
-
-       /**
-        * Bundles which should be removed from the project's bundles directory.
-        *
-        * @parameter
-        */
-       private ArtifactDefinition[] bundlesToRemove;
-
-       /**
-        * If true, install the default bundles.
-        *
-        * @parameter default-value="true"
-        */
-       private boolean installDefaultBundles;
+public class PreparePackageMojo extends AbstractLaunchpadFrameworkMojo {
 
        /**
         * The output directory for the default bundles in a WAR-packaged 
project,
@@ -97,45 +82,43 @@ public class PreparePackageMojo extends 
AbstractBundleListMojo {
         */
        private File buildOutputDirectory;
 
+    /**
+     * To look up Archiver/UnArchiver implementations
+     *
+     * @component
+     */
+    private ArchiverManager archiverManager;
+
        public void executeWithArtifacts() throws MojoExecutionException, 
MojoFailureException {
                copyBaseArtifact();
-               if (installDefaultBundles) {
-                       unpackDefaultBundles();
-               }
-               copyAdditionalBundles();
-               copyWebSupportBundle();
-               removeBundles();
+               copyBundles(getBundleList(), getOutputDirectory());
                if (JAR.equals(packaging)) {
                        unpackBaseArtifact();
                }
        }
 
-       private void removeBundles() throws MojoExecutionException {
-           if (bundlesToRemove != null) {
-               File bundleBaseDir = new File(getOutputDirectory(), 
String.format(
-                       "%s/%s", baseDestination, bundlesDirectory));
-
-               for (ArtifactDefinition def : bundlesToRemove) {
-                   DirectoryScanner scanner = new DirectoryScanner();
-                   scanner.setBasedir(bundleBaseDir);
-                   scanner.setIncludes(new String[] { "**/" + 
def.getArtifactId() + "-*.*"});
-                   scanner.scan();
-                   for (String toRemove : scanner.getIncludedFiles()) {
-                       getLog().info("Deleting " + toRemove);
-                       new File(toRemove).delete();
-                   }
-               }
-           }
-       }
+       protected void initArtifactDefinitions(Properties dependencies) {
+               if (base == null) {
+                       base = new ArtifactDefinition();
+               }
+               base.initDefaults(dependencies.getProperty("base"));
 
-       private void copyAdditionalBundles() throws MojoExecutionException {
-               if (additionalBundles != null) {
-                       for (int i = 0; i < additionalBundles.length; i++) {
-                               copy(additionalBundles[i], 
getOutputDirectory());
-                       }
+               if (jarWebSupport == null) {
+                       jarWebSupport = new ArtifactDefinition();
                }
+               
jarWebSupport.initDefaults(dependencies.getProperty("jarWebSupport"));
        }
 
+       /**
+     * Add the JAR Web Support bundle to the bundle list.
+     */
+    @Override
+    protected void initBundleList(BundleList bundleList) {
+        if (packaging.equals(JAR)) {
+            bundleList.add(jarWebSupport.toBundle());
+        }
+    }
+
        private void copyBaseArtifact() throws MojoExecutionException {
                Artifact artifact = getBaseArtifact();
                if (artifact == null) {
@@ -166,13 +149,6 @@ public class PreparePackageMojo extends 
AbstractBundleListMojo {
                }
        }
 
-       private void copyWebSupportBundle() throws MojoExecutionException {
-               if (JAR.equals(packaging)) {
-                       copy(jarWebSupport, getOutputDirectory());
-               }
-
-       }
-
        private Artifact getBaseArtifact() throws MojoExecutionException {
                Artifact baseDependency = getBaseDependency();
                if (baseDependency == null) {
@@ -198,20 +174,6 @@ public class PreparePackageMojo extends 
AbstractBundleListMojo {
                }
        }
 
-
-
-       protected void initArtifactDefinitions(Properties dependencies) {
-               if (base == null) {
-                       base = new ArtifactDefinition();
-               }
-               base.initDefaults(dependencies.getProperty("base"));
-
-               if (jarWebSupport == null) {
-                       jarWebSupport = new ArtifactDefinition();
-               }
-               
jarWebSupport.initDefaults(dependencies.getProperty("jarWebSupport"));
-       }
-
        private void unpackBaseArtifact() throws MojoExecutionException {
                Artifact artifact = getBaseDependency();
                if (artifact == null) {
@@ -224,8 +186,36 @@ public class PreparePackageMojo extends 
AbstractBundleListMojo {
                unpack(artifact.getFile(), buildOutputDirectory, null, null);
        }
 
-       private void unpackDefaultBundles() throws MojoExecutionException {
-               outputBundleList(getOutputDirectory());
+    private void unpack(File source, File destination, String includes, String 
excludes)
+            throws MojoExecutionException {
+        getLog().info("Unpacking " + source.getPath() + " to\n  " + 
destination.getPath());
+        try {
+            destination.mkdirs();
 
-       }
+            UnArchiver unArchiver = archiverManager.getUnArchiver(source);
+
+            unArchiver.setSourceFile(source);
+            unArchiver.setDestDirectory(destination);
+
+            if (StringUtils.isNotEmpty(excludes) || 
StringUtils.isNotEmpty(includes)) {
+                IncludeExcludeFileSelector[] selectors = new 
IncludeExcludeFileSelector[] { new IncludeExcludeFileSelector() };
+
+                if (StringUtils.isNotEmpty(excludes)) {
+                    selectors[0].setExcludes(excludes.split(","));
+                }
+
+                if (StringUtils.isNotEmpty(includes)) {
+                    selectors[0].setIncludes(includes.split(","));
+                }
+
+                unArchiver.setFileSelectors(selectors);
+            }
+
+            unArchiver.extract();
+        } catch (NoSuchArchiverException e) {
+            throw new MojoExecutionException("Unable to find archiver for " + 
source.getPath(), e);
+        } catch (ArchiverException e) {
+            throw new MojoExecutionException("Unable to unpack " + 
source.getPath(), e);
+        }
+    }
 }
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/bundlelist/BaseBundle.java
 
b/src/main/java/org/apache/sling/maven/projectsupport/bundlelist/BaseBundle.java
new file mode 100644
index 0000000..5c9b683
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/bundlelist/BaseBundle.java
@@ -0,0 +1,33 @@
+/*
+ * 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.maven.projectsupport.bundlelist;
+
+public abstract class BaseBundle {
+
+    public abstract String getArtifactId();
+
+    public abstract String getClassifier();
+
+    public abstract String getGroupId();
+
+    public abstract int getStartLevel();
+
+    public abstract String getType();
+
+    public abstract String getVersion();
+
+}
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/bundlelist/BaseBundleList.java
 
b/src/main/java/org/apache/sling/maven/projectsupport/bundlelist/BaseBundleList.java
new file mode 100644
index 0000000..cd838c8
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/bundlelist/BaseBundleList.java
@@ -0,0 +1,92 @@
+/*
+ * 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.maven.projectsupport.bundlelist;
+
+import java.util.List;
+
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.StartLevel;
+
+public abstract class BaseBundleList {
+
+    public abstract List<StartLevel> getStartLevels();
+
+    public Bundle get(Bundle bundle, boolean compareVersions) {
+        for (StartLevel sl : getStartLevels()) {
+            Bundle foundBundle = sl.getBundle(bundle, compareVersions);
+            if (foundBundle != null) {
+                return foundBundle;
+            }
+        }
+        return null;
+    }
+
+    public boolean remove(Bundle bundle, boolean compareVersions) {
+        for (StartLevel sl : getStartLevels()) {
+            if (sl.removeBundle(bundle, compareVersions)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * Merge the current bundle list with an additional list.
+     * @see add(Bundle)
+     *
+     * @param bundleList the new bundle list
+     */
+    public void merge(BundleList bundleList) {
+        for (StartLevel sl : bundleList.getStartLevels()) {
+            for (Bundle bnd : sl.getBundles()) {
+                add(bnd);
+            }
+        }
+    }
+
+    /**
+     * Add an artifact definition. If it already exists, update the version, 
but
+     * do not change the start level.
+     *
+     * @param newBnd the bundle to add
+     */
+    public void add(Bundle newBnd) {
+        Bundle current = get(newBnd, false);
+        if (current != null) {
+
+        } else {
+            StartLevel startLevel = 
getOrCreateStartLevel(newBnd.getStartLevel());
+            startLevel.getBundles().add(newBnd);
+        }
+
+    }
+
+    private StartLevel getOrCreateStartLevel(int startLevel) {
+        for (StartLevel sl : getStartLevels()) {
+            if (sl.getLevel() == startLevel) {
+                return sl;
+            }
+        }
+
+        StartLevel sl = new StartLevel();
+        sl.setLevel(startLevel);
+        return sl;
+    }
+
+}
diff --git 
a/src/main/java/org/apache/sling/maven/projectsupport/bundlelist/BaseStartLevel.java
 
b/src/main/java/org/apache/sling/maven/projectsupport/bundlelist/BaseStartLevel.java
new file mode 100644
index 0000000..b7e5923
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/maven/projectsupport/bundlelist/BaseStartLevel.java
@@ -0,0 +1,60 @@
+/*
+ * 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.maven.projectsupport.bundlelist;
+
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.Bundle;
+
+public abstract class BaseStartLevel {
+
+    public abstract List<Bundle> getBundles();
+
+    public boolean removeBundle(Bundle bundle, boolean compareVersions) {
+        for (ListIterator<Bundle> it = getBundles().listIterator(); 
it.hasNext();) {
+            if (isSameArtifact(bundle, it.next(), compareVersions)) {
+                it.remove();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean containsBundle(Bundle bundle, boolean compareVersions) {
+        for (Bundle compare : getBundles()) {
+            return isSameArtifact(bundle, compare, compareVersions);
+        }
+        return false;
+    }
+
+    public Bundle getBundle(Bundle bundle, boolean compareVersions) {
+        for (Bundle compare : getBundles()) {
+            if (isSameArtifact(bundle, compare, compareVersions)) {
+                return compare;
+            }
+        }
+        return null;
+    }
+
+    private boolean isSameArtifact(Bundle bundle1, Bundle bundle2, boolean 
compareVersions) {
+        boolean result = compareVersions ? 
bundle1.getVersion().equals(bundle2) : true;
+        return result && 
bundle1.getArtifactId().equals(bundle2.getArtifactId())
+                && bundle1.getGroupId().equals(bundle2.getGroupId()) && 
bundle1.getType().equals(bundle2.getType());
+    }
+
+}
diff --git a/src/main/mdo/bundle-list.xml b/src/main/mdo/bundle-list.xml
index db071ab..8c078b2 100644
--- a/src/main/mdo/bundle-list.xml
+++ b/src/main/mdo/bundle-list.xml
@@ -35,6 +35,7 @@
             <name>BundleList</name>
             <description>List of bundles.</description>
             <version>1.0.0</version>
+            
<superClass>org.apache.sling.maven.projectsupport.bundlelist.BaseBundleList</superClass>
             <fields>
                 <field>
                     <name>startLevels</name>
@@ -49,6 +50,7 @@
         <class xml.tagName="startLevel">
                <name>StartLevel</name>
             <version>1.0.0</version>
+            
<superClass>org.apache.sling.maven.projectsupport.bundlelist.BaseStartLevel</superClass>
             <fields>
                <field xml.attribute="true">
                        <name>level</name>
@@ -68,6 +70,7 @@
         <class xml.tagName="bundle">
             <name>Bundle</name>
             <description>A bundle.</description>
+            
<superClass>org.apache.sling.maven.projectsupport.bundlelist.BaseBundle</superClass>
             <fields>
                 <field>
                     <name>groupId</name>
diff --git 
a/src/test/java/org/apache/sling/maven/projectsupport/PreparePackageMojoTest.java
 
b/src/test/java/org/apache/sling/maven/projectsupport/PreparePackageMojoTest.java
index c46f338..51fe815 100644
--- 
a/src/test/java/org/apache/sling/maven/projectsupport/PreparePackageMojoTest.java
+++ 
b/src/test/java/org/apache/sling/maven/projectsupport/PreparePackageMojoTest.java
@@ -35,8 +35,8 @@ public class PreparePackageMojoTest {
                makeArtifactAssertions(mojo, "base", "org.apache.sling",
                                "org.apache.sling.launchpad.base", null, "jar", 
null, 0);
 
-               makeArtifactAssertions(mojo, "defaultBundles", 
"org.apache.sling",
-                               "org.apache.sling.launchpad", "RELEASE", "jar", 
"bundles", 0);
+               //makeArtifactAssertions(mojo, "defaultBundles", 
"org.apache.sling",
+               //              "org.apache.sling.launchpad", "RELEASE", "jar", 
"bundles", 0);
 
         makeArtifactAssertions(mojo, "defaultBundleList", "org.apache.sling",
                 "org.apache.sling.launchpad", "RELEASE", "xml", "bundlelist", 
0);

-- 
To stop receiving notification emails like this one, please contact
"[email protected]" <[email protected]>.

Reply via email to