ACE-4463 - make sure DA does not try to install DPs with non-unique resources.

- added checks during the creation of an AbstractDeploymentPackage;
- added itests verifying this behaviour for bundles.



git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1581302 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java b/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java
index 808ce34..3009a18 100644
--- a/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java
+++ b/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java
@@ -23,6 +23,7 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.jar.Manifest;
 
@@ -37,8 +38,9 @@
 import org.osgi.service.deploymentadmin.spi.ResourceProcessor;
 
 /**
- * Base class for various types of deployment packages. Indifferent in regard to how the
- * deployment package data is obtained, this should be handled by extending classes.
+ * Base class for various types of deployment packages. Indifferent in regard to
+ * how the deployment package data is obtained, this should be handled by
+ * extending classes.
  */
 public abstract class AbstractDeploymentPackage implements DeploymentPackage {
     /**
@@ -50,48 +52,90 @@
         private static final BundleInfoImpl[] BUNDLE_INFO_IMPLS = new BundleInfoImpl[] {};
 
         public String getHeader(String header) {
-            if (Constants.DEPLOYMENTPACKAGE_SYMBOLICMAME.equals(header)) { return ""; }
-            else if (Constants.DEPLOYMENTPACKAGE_VERSION.equals(header)) { return Version.emptyVersion.toString(); }
-            else { return null; }
+            if (Constants.DEPLOYMENTPACKAGE_SYMBOLICMAME.equals(header)) {
+                return "";
+            } else if (Constants.DEPLOYMENTPACKAGE_VERSION.equals(header)) {
+                return Version.emptyVersion.toString();
+            } else {
+                return null;
+            }
         }
 
-        public Bundle getBundle(String symbolicName) { return null; }
+        public Bundle getBundle(String symbolicName) {
+            return null;
+        }
 
-        public BundleInfo[] getBundleInfos() { return BUNDLE_INFO_IMPLS; }
+        public BundleInfo[] getBundleInfos() {
+            return BUNDLE_INFO_IMPLS;
+        }
 
-        public BundleInfoImpl[] getBundleInfoImpls() { return BUNDLE_INFO_IMPLS; }
+        public BundleInfoImpl[] getBundleInfoImpls() {
+            return BUNDLE_INFO_IMPLS;
+        }
 
-        public ResourceInfoImpl[] getResourceInfos() { return RESOURCE_INFO_IMPLS; }
+        public ResourceInfoImpl[] getResourceInfos() {
+            return RESOURCE_INFO_IMPLS;
+        }
 
-        public String getName() { return ""; }
+        public String getName() {
+            return "";
+        }
 
-        public String getResourceHeader(String resource, String header) { return null; }
+        public String getResourceHeader(String resource, String header) {
+            return null;
+        }
 
-        public ServiceReference getResourceProcessor(String resource) { return null; }
+        public ServiceReference getResourceProcessor(String resource) {
+            return null;
+        }
 
-        public String[] getResources() { return STRINGS; }
+        public String[] getResources() {
+            return STRINGS;
+        }
 
-        public Version getVersion() { return Version.emptyVersion; }
+        public Version getVersion() {
+            return Version.emptyVersion;
+        }
 
-        public boolean isStale() { return true; }
+        public boolean isStale() {
+            return true;
+        }
 
-        public void uninstall() throws DeploymentException { throw new IllegalStateException("Can not uninstall stale DeploymentPackage"); }
+        public void uninstall() throws DeploymentException {
+            throw new IllegalStateException("Can not uninstall stale DeploymentPackage");
+        }
 
-        public boolean uninstallForced() throws DeploymentException { throw new IllegalStateException("Can not uninstall stale DeploymentPackage"); }
+        public boolean uninstallForced() throws DeploymentException {
+            throw new IllegalStateException("Can not uninstall stale DeploymentPackage");
+        }
 
-        public InputStream getBundleStream(String symbolicName) throws IOException { return null; }
+        public InputStream getBundleStream(String symbolicName) throws IOException {
+            return null;
+        }
 
-        public BundleInfoImpl[] getOrderedBundleInfos() { return BUNDLE_INFO_IMPLS; }
+        public BundleInfoImpl[] getOrderedBundleInfos() {
+            return BUNDLE_INFO_IMPLS;
+        }
 
-        public ResourceInfoImpl[] getOrderedResourceInfos() { return RESOURCE_INFO_IMPLS; }
+        public ResourceInfoImpl[] getOrderedResourceInfos() {
+            return RESOURCE_INFO_IMPLS;
+        }
 
-        public InputStream getCurrentEntryStream() { throw new UnsupportedOperationException(); }
+        public InputStream getCurrentEntryStream() {
+            throw new UnsupportedOperationException();
+        }
 
-        public AbstractInfo getNextEntry() throws IOException { throw new UnsupportedOperationException(); }
+        public AbstractInfo getNextEntry() throws IOException {
+            throw new UnsupportedOperationException();
+        }
 
-        public String getDisplayName() { return ""; }
+        public String getDisplayName() {
+            return "";
+        }
 
-        public URL getIcon() { return null; }
+        public URL getIcon() {
+            return null;
+        }
     }
 
     protected static final AbstractDeploymentPackage EMPTY_PACKAGE = new EmptyDeploymentPackage();
@@ -106,7 +150,7 @@
     private final String[] m_resourcePaths;
     private final boolean m_isFixPackage;
     private boolean m_isStale;
-    
+
     /* Constructor only for use by the emptyPackage static variable */
     private AbstractDeploymentPackage() {
         m_bundleContext = null;
@@ -123,21 +167,41 @@
      *
      * @param manifest The manifest of the deployment package.
      * @param bundleContext The bundle context.
-     * @throws DeploymentException Thrown if the specified manifest does not describe a valid deployment package.
+     * @throws DeploymentException Thrown if the specified manifest does not
+     *         describe a valid deployment package.
      */
     public AbstractDeploymentPackage(Manifest manifest, BundleContext bundleContext, DeploymentAdminImpl deploymentAdmin) throws DeploymentException {
         m_manifest = new DeploymentPackageManifest(manifest);
         m_isFixPackage = m_manifest.getFixPackage() != null;
         m_bundleContext = bundleContext;
         m_deploymentAdmin = deploymentAdmin;
-        m_bundleInfos = (BundleInfoImpl[]) m_manifest.getBundleInfos().toArray(new BundleInfoImpl[0]);
-        for(int i = 0; i < m_bundleInfos.length; i++) {
-            m_nameToBundleInfo.put(m_bundleInfos[i].getSymbolicName(), m_bundleInfos[i]);
-            m_pathToEntry.put(m_bundleInfos[i].getPath(), m_bundleInfos[i]);
+
+        List bundleInfos = m_manifest.getBundleInfos();
+        m_bundleInfos = (BundleInfoImpl[]) bundleInfos.toArray(new BundleInfoImpl[bundleInfos.size()]);
+
+        for (int i = 0; i < m_bundleInfos.length; i++) {
+            String bsn = m_bundleInfos[i].getSymbolicName();
+            if (m_nameToBundleInfo.put(bsn, m_bundleInfos[i]) != null) {
+                // FELIX-4463: make sure that the DP is consistent...
+                throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Duplicate bundle present in deployment package: " + bsn);
+            }
+
+            String path = m_bundleInfos[i].getPath();
+            if (m_pathToEntry.put(path, m_bundleInfos[i]) != null) {
+                // FELIX-4463: make sure that the DP is consistent...
+                throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Non-unique path present in deployment package: " + path);
+            }
         }
-        m_resourceInfos =  (ResourceInfoImpl[]) m_manifest.getResourceInfos().toArray(new ResourceInfoImpl[0]);
+
+        List resourceInfos = m_manifest.getResourceInfos();
+        m_resourceInfos = (ResourceInfoImpl[]) resourceInfos.toArray(new ResourceInfoImpl[resourceInfos.size()]);
+
         for (int i = 0; i < m_resourceInfos.length; i++) {
-            m_pathToEntry.put(m_resourceInfos[i].getPath(), m_resourceInfos[i]);
+            String path = m_resourceInfos[i].getPath();
+            if (m_pathToEntry.put(path, m_resourceInfos[i]) != null) {
+                // FELIX-4463: make sure that the DP is consistent...
+                throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Non-unique path present in deployment package: " + path);
+            }
         }
         m_resourcePaths = (String[]) m_pathToEntry.keySet().toArray(new String[m_pathToEntry.size()]);
     }
@@ -146,7 +210,7 @@
         if (isStale()) {
             throw new IllegalStateException("Can not get bundle from stale deployment package.");
         }
-        
+
         BundleInfo bundleInfo = (BundleInfo) m_nameToBundleInfo.get(symbolicName);
         if (bundleInfo != null) {
             Version version = bundleInfo.getVersion();
@@ -166,18 +230,22 @@
     }
 
     /**
-     * Returns the bundles of this deployment package as an array of <code>BundleInfoImpl</code> objects.
+     * Returns the bundles of this deployment package as an array of
+     * <code>BundleInfoImpl</code> objects.
      *
-     * @return Array containing <code>BundleInfoImpl</code> objects for each bundle this deployment package.
+     * @return Array containing <code>BundleInfoImpl</code> objects for each
+     *         bundle this deployment package.
      */
     public BundleInfoImpl[] getBundleInfoImpls() {
         return (BundleInfoImpl[]) m_bundleInfos.clone();
     }
 
     /**
-     * Returns the processed resources of this deployment package as an array of <code>ResourceInfoImpl</code> objects.
+     * Returns the processed resources of this deployment package as an array of
+     * <code>ResourceInfoImpl</code> objects.
      *
-     * @return Array containing <code>ResourceInfoImpl</code> objects for each processed resource of this deployment package.
+     * @return Array containing <code>ResourceInfoImpl</code> objects for each
+     *         processed resource of this deployment package.
      */
     public ResourceInfoImpl[] getResourceInfos() {
         return (ResourceInfoImpl[]) m_resourceInfos.clone();
@@ -186,7 +254,8 @@
     /**
      * Determines whether this deployment package is a fix package.
      *
-     * @return True if this deployment package is a fix package, false otherwise.
+     * @return True if this deployment package is a fix package, false
+     *         otherwise.
      */
     public boolean isFixPackage() {
         return m_isFixPackage;
@@ -199,7 +268,7 @@
     public String getName() {
         return m_manifest.getSymbolicName();
     }
-    
+
     public String getDisplayName() {
         return getHeader("DeploymentPackage-Name");
     }
@@ -208,10 +277,10 @@
         String icon = getHeader("DeploymentPackage-Icon");
         if (icon == null) {
             return null;
-        }
-        else {
+        } else {
             try {
-                // TODO spec states this must be a local resource, but we don't make
+                // TODO spec states this must be a local resource, but we don't
+// make
                 // sure of that yet
                 return new URL(icon);
             }
@@ -241,13 +310,12 @@
                     ServiceReference[] services = m_bundleContext.getServiceReferences(ResourceProcessor.class.getName(), "(" + org.osgi.framework.Constants.SERVICE_PID + "=" + processor + ")");
                     if (services != null && services.length > 0) {
                         return services[0];
-                    }
-                    else {
-                    	return null;
+                    } else {
+                        return null;
                     }
                 }
                 catch (InvalidSyntaxException e) {
-                	// TODO: log this
+                    // TODO: log this
                     return null;
                 }
             }
@@ -264,9 +332,11 @@
     }
 
     /**
-     * If this deployment package is a fix package this method determines the version range this deployment package can be applied to.
+     * If this deployment package is a fix package this method determines the
+     * version range this deployment package can be applied to.
      *
-     * @return <code>VersionRange</code> the fix package can be applied to or <code>null</code> if it is not a fix package.
+     * @return <code>VersionRange</code> the fix package can be applied to or
+     *         <code>null</code> if it is not a fix package.
      */
     public VersionRange getVersionRange() {
         return m_manifest.getFixPackage();
@@ -275,15 +345,16 @@
     public boolean isStale() {
         return m_isStale;
     }
-    
+
     /**
-     * @return <code>true</code> if this package is actually an empty package used for 
-     *         installing new deployment packages, <code>false</code> otherwise.
+     * @return <code>true</code> if this package is actually an empty package
+     *         used for installing new deployment packages, <code>false</code>
+     *         otherwise.
      */
     public boolean isNew() {
         return this == EMPTY_PACKAGE;
     }
-    
+
     public void setStale(boolean isStale) {
         m_isStale = isStale;
     }
@@ -294,7 +365,8 @@
         }
         try {
             m_deploymentAdmin.uninstallDeploymentPackage(this, false /* force */);
-        } finally {
+        }
+        finally {
             setStale(true);
         }
     }
@@ -305,31 +377,41 @@
         }
         try {
             m_deploymentAdmin.uninstallDeploymentPackage(this, true /* force */);
-        } finally {
+        }
+        finally {
             setStale(true);
         }
         return true;
     }
 
     /**
-     * Determines the bundles of this deployment package in the order in which they were originally received.
+     * Determines the bundles of this deployment package in the order in which
+     * they were originally received.
      *
-     * @return Array containing <code>BundleInfoImpl</code> objects of the bundles in this deployment package, ordered in the way they appeared when the deployment package was first received.
+     * @return Array containing <code>BundleInfoImpl</code> objects of the
+     *         bundles in this deployment package, ordered in the way they
+     *         appeared when the deployment package was first received.
      */
     public abstract BundleInfoImpl[] getOrderedBundleInfos();
 
     /**
-     * Determines the resources of this deployment package in the order in which they were originally received.
+     * Determines the resources of this deployment package in the order in which
+     * they were originally received.
      *
-     * @return Array containing <code>ResourceInfoImpl</code> objects of all processed resources in this deployment package, ordered in the way they appeared when the deployment package was first received
+     * @return Array containing <code>ResourceInfoImpl</code> objects of all
+     *         processed resources in this deployment package, ordered in the
+     *         way they appeared when the deployment package was first received
      */
     public abstract ResourceInfoImpl[] getOrderedResourceInfos();
 
     /**
-     * Determines the info about a processed resource based on it's path/resource-id.
+     * Determines the info about a processed resource based on it's
+     * path/resource-id.
      *
      * @param path String containing a (processed) resource path
-     * @return <code>ResourceInfoImpl</code> for the resource identified by the specified path or null if the path is unknown or does not describe a processed resource
+     * @return <code>ResourceInfoImpl</code> for the resource identified by the
+     *         specified path or null if the path is unknown or does not
+     *         describe a processed resource
      */
     public ResourceInfoImpl getResourceInfoByPath(String path) {
         AbstractInfo info = (AbstractInfo) m_pathToEntry.get(path);
@@ -340,10 +422,13 @@
     }
 
     /**
-     * Determines the info about either a bundle or processed resource based on it's path/resource-id.
+     * Determines the info about either a bundle or processed resource based on
+     * it's path/resource-id.
      *
-     * @param path String containing a resource path (either bundle or processed resource)
-     * @return <code>AbstractInfoImpl</code> for the resource identified by the specified path or null if the path is unknown
+     * @param path String containing a resource path (either bundle or processed
+     *        resource)
+     * @return <code>AbstractInfoImpl</code> for the resource identified by the
+     *         specified path or null if the path is unknown
      */
     protected AbstractInfo getAbstractInfoByPath(String path) {
         return (AbstractInfo) m_pathToEntry.get(path);
@@ -353,7 +438,9 @@
      * Determines the info about a bundle based on it's path/resource-id.
      *
      * @param path String containing a bundle path
-     * @return <code>BundleInfoImpl</code> for the bundle resource identified by the specified path or null if the path is unknown or does not describe a bundle resource
+     * @return <code>BundleInfoImpl</code> for the bundle resource identified by
+     *         the specified path or null if the path is unknown or does not
+     *         describe a bundle resource
      */
     public BundleInfoImpl getBundleInfoByPath(String path) {
         AbstractInfo info = (AbstractInfo) m_pathToEntry.get(path);
@@ -364,38 +451,49 @@
     }
 
     /**
-     * Determines the info about a bundle resource based on the bundle symbolic name.
+     * Determines the info about a bundle resource based on the bundle symbolic
+     * name.
      *
      * @param symbolicName String containing a bundle symbolic name
-     * @return <code>BundleInfoImpl</code> for the bundle identified by the specified symbolic name or null if the symbolic name is unknown
+     * @return <code>BundleInfoImpl</code> for the bundle identified by the
+     *         specified symbolic name or null if the symbolic name is unknown
      */
     public BundleInfoImpl getBundleInfoByName(String symbolicName) {
         return (BundleInfoImpl) m_nameToBundleInfo.get(symbolicName);
     }
 
     /**
-     * Determines the data stream of a bundle resource based on the bundle symbolic name
+     * Determines the data stream of a bundle resource based on the bundle
+     * symbolic name
      *
      * @param symbolicName Bundle symbolic name
-     * @return Stream to the bundle identified by the specified symbolic name or null if no such bundle exists in this deployment package.
-     * @throws IOException If the bundle can not be properly offered as an inputstream
+     * @return Stream to the bundle identified by the specified symbolic name or
+     *         null if no such bundle exists in this deployment package.
+     * @throws IOException If the bundle can not be properly offered as an
+     *         inputstream
      */
     public abstract InputStream getBundleStream(String symbolicName) throws IOException;
 
     /**
-     * Determines the next resource entry in this deployment package based on the order in which the resources appeared when the package was originally received.
+     * Determines the next resource entry in this deployment package based on
+     * the order in which the resources appeared when the package was originally
+     * received.
      *
-     * @return <code>AbstractInfo</code> describing the next resource entry (as determined by the order in which the deployment package was received originally) or null if there is no next entry
+     * @return <code>AbstractInfo</code> describing the next resource entry (as
+     *         determined by the order in which the deployment package was
+     *         received originally) or null if there is no next entry
      * @throws IOException if the next entry can not be properly determined
      */
     public abstract AbstractInfo getNextEntry() throws IOException;
 
     /**
-     * Determines the data stream to the current entry of this deployment package, use this together with the <code>getNextEntry</code> method.
+     * Determines the data stream to the current entry of this deployment
+     * package, use this together with the <code>getNextEntry</code> method.
      *
-     * @return Stream to the current resource in the deployment package (as determined by the order in which the deployment package was received originally) or null if there is no entry
+     * @return Stream to the current resource in the deployment package (as
+     *         determined by the order in which the deployment package was
+     *         received originally) or null if there is no entry
      */
     public abstract InputStream getCurrentEntryStream();
 
 }
-
diff --git a/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallDeploymentPackageTest.java b/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallDeploymentPackageTest.java
index 3570358..ffd1666 100644
--- a/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallDeploymentPackageTest.java
+++ b/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallDeploymentPackageTest.java
@@ -23,6 +23,7 @@
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.PaxExam;
 import org.osgi.framework.Bundle;
+import org.osgi.service.deploymentadmin.BundleInfo;
 import org.osgi.service.deploymentadmin.DeploymentException;
 import org.osgi.service.deploymentadmin.DeploymentPackage;
 
@@ -30,13 +31,14 @@
  * Provides test cases regarding the use of "normal" deployment packages in DeploymentAdmin.
  */
 @RunWith(PaxExam.class)
-public class InstallDeploymentPackageTest extends BaseIntegrationTest {
-
+public class InstallDeploymentPackageTest extends BaseIntegrationTest
+{
     /**
-     * FELIX-4409/4410 - test the installation of an invalid deployment package.
+     * FELIX-4409/4410/4463 - test the installation of an invalid deployment package.
      */
     @Test
-    public void testInstallInvalidDeploymentPackageFail() throws Exception {
+    public void testInstallInvalidDeploymentPackageFail() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
         // incluse two different versions of the same bundle (with the same BSN), this is *not* allowed per the DA spec...
         dpBuilder
@@ -52,21 +54,44 @@
         {
             // Ok; expected...
         }
-        
+
         // Verify that none of the bundles are installed...
         assertBundleNotExists("testbundles.bundleapi", "1.0.0");
         assertBundleNotExists("testbundles.bundleapi", "2.0.0");
     }
 
     /**
+     * FELIX-1835 - test whether we can install bundles with a non-root path inside the DP.
+     */
+    @Test
+    public void testInstallBundlesWithPathsOk() throws Exception
+    {
+        DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
+        // incluse two different versions of the same bundle (with the same BSN), this is *not* allowed per the DA spec...
+        dpBuilder
+            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundleapi1", "bundleapi", "1.0.0")).setFilename("bundles/bundleapi1.jar"))
+            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundleimpl1", "bundleimpl", "1.0.0")).setFilename("bundles/bundleimpl1.jar"));
+
+        DeploymentPackage dp = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
+        assertNotNull(dp);
+
+        BundleInfo[] bundleInfos = dp.getBundleInfos();
+        assertEquals(2, bundleInfos.length);
+
+        // Verify that none of the bundles are installed...
+        assertBundleExists("testbundles.bundleapi", "1.0.0");
+        assertBundleExists("testbundles.bundleimpl", "1.0.0");
+    }
+
+    /**
      * Tests that adding the dependency for a bundle in an update package causes the depending bundle to be resolved and started.
      */
     @Test
-    public void testInstallBundleWithDependencyInPackageUpdateOk() throws Exception {
+    public void testInstallBundleWithDependencyInPackageUpdateOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
         // missing bundle1 as dependency...
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -96,10 +121,10 @@
      * Tests that installing a bundle with a dependency installed by another deployment package is not started, but is resolved.
      */
     @Test
-    public void testInstallBundleWithDependencyInSeparatePackageOk() throws Exception {
+    public void testInstallBundleWithDependencyInSeparatePackageOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -115,8 +140,7 @@
 
         dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
         // as missing bundle1...
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
 
         DeploymentPackage dp2 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp2);
@@ -137,7 +161,8 @@
      * Tests that if an exception is thrown in the start method of a bundle, the installation is not rolled back.
      */
     @Test
-    public void testInstallBundleWithExceptionThrownInStartCausesNoRollbackOk() throws Exception {
+    public void testInstallBundleWithExceptionThrownInStartCausesNoRollbackOk() throws Exception
+    {
         System.setProperty("bundle3", "start");
 
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
@@ -164,7 +189,8 @@
      * Tests that installing a bundle along with a fragment bundle succeeds (DA should not try to start the fragment, see FELIX-4167).
      */
     @Test
-    public void testInstallBundleWithFragmentOk() throws Exception {
+    public void testInstallBundleWithFragmentOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
         dpBuilder
             .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
@@ -188,10 +214,10 @@
      * Tests that installing a bundle whose dependencies cannot be met, is installed, but not started.
      */
     @Test
-    public void testInstallBundleWithMissingDependencyOk() throws Exception {
+    public void testInstallBundleWithMissingDependencyOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp);
@@ -206,18 +232,16 @@
         assertTrue(isBundleInstalled(dp.getBundle(getSymbolicName("bundle2"))));
     }
 
-
     /**
      * Tests that installing a bundle along with other (non-bundle) artifacts succeeds.
      */
     @Test
-    public void testInstallBundleWithOtherArtifactsOk() throws Exception {
+    public void testInstallBundleWithOtherArtifactsOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
         dpBuilder
             .add(dpBuilder.createResourceProcessorResource().setUrl(getTestBundle("rp1")))
-            .add(
-                dpBuilder.createResource().setResourceProcessorPID(TEST_FAILING_BUNDLE_RP1)
-                    .setUrl(getTestResource("test-config1.xml")))
+            .add(dpBuilder.createResource().setResourceProcessorPID(TEST_FAILING_BUNDLE_RP1).setUrl(getTestResource("test-config1.xml")))
             .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle3")));
 
         DeploymentPackage dp = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
@@ -236,10 +260,10 @@
      * Tests that installing a new bundle works as expected.
      */
     @Test
-    public void testInstallSingleValidBundleOk() throws Exception {
+    public void testInstallSingleValidBundleOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
 
         DeploymentPackage dp = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp);
@@ -256,7 +280,8 @@
      * Tests that installing two bundles works as expected.
      */
     @Test
-    public void testInstallTwoValidBundlesOk() throws Exception {
+    public void testInstallTwoValidBundlesOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
         dpBuilder
             .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
@@ -280,7 +305,8 @@
      * Tests that if an exception is thrown during the uninstall of a bundle, the installation/update continues and succeeds.
      */
     @Test
-    public void testUninstallBundleWithExceptionThrownInStopCauseNoRollbackOk() throws Exception {
+    public void testUninstallBundleWithExceptionThrownInStopCauseNoRollbackOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
         dpBuilder
             .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
@@ -317,7 +343,8 @@
      * Tests that if an exception is thrown during the stop of a bundle, the installation/update continues and succeeds.
      */
     @Test
-    public void testUpdateBundleWithExceptionThrownInStopCauseNoRollbackOk() throws Exception {
+    public void testUpdateBundleWithExceptionThrownInStopCauseNoRollbackOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
         dpBuilder
             .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
diff --git a/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallFixPackageTest.java b/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallFixPackageTest.java
index 399d213..e12ab7c 100644
--- a/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallFixPackageTest.java
+++ b/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallFixPackageTest.java
@@ -36,16 +36,17 @@
  * Provides test cases regarding the use of "fix-packages" in DeploymentAdmin.
  */
 @RunWith(PaxExam.class)
-public class InstallFixPackageTest extends BaseIntegrationTest {
+public class InstallFixPackageTest extends BaseIntegrationTest
+{
 
     /**
      * Tests that we can install a new bundle through a fix-package.
      */
     @Test
-    public void testInstallBundleWithDependencyInFixPackageUpdateOk() throws Exception {
+    public void testInstallBundleWithDependencyInFixPackageUpdateOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -58,10 +59,7 @@
         assertEquals(Bundle.INSTALLED, bundle.getState());
 
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
 
         DeploymentPackage dp2 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp2);
@@ -81,10 +79,10 @@
      * Tests that it is not possible to install a fix package if it specifies a fix-version range that falls outside the installed target deployment package.
      */
     @Test
-    public void testInstallFixPackageOutsideLowerTargetRangeFail() throws Exception {
+    public void testInstallFixPackageOutsideLowerTargetRangeFail() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -97,16 +95,16 @@
         assertEquals(Bundle.INSTALLED, bundle.getState());
 
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("(1.0,2.0)") // should not include version 1.0.0!
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
+        dpBuilder.setFixPackage("(1.0,2.0)") // should not include version 1.0.0!
+        .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
 
-        try {
+        try
+        {
             m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
             fail("Succeeded into installing fix package for undefined target package?!");
         }
-        catch (DeploymentException exception) {
+        catch (DeploymentException exception)
+        {
             // Ok; expected
             assertDeploymentException(CODE_MISSING_FIXPACK_TARGET, exception);
         }
@@ -116,10 +114,10 @@
      * Tests that it is not possible to install a fix package if it specifies a fix-version range that falls outside the installed target deployment package.
      */
     @Test
-    public void testInstallFixPackageOutsideUpperTargetRangeFail() throws Exception {
+    public void testInstallFixPackageOutsideUpperTargetRangeFail() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -132,16 +130,16 @@
         assertEquals(Bundle.INSTALLED, bundle.getState());
 
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[0.9,1.0)") // should not include version 1.0.0!
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
+        dpBuilder.setFixPackage("[0.9,1.0)") // should not include version 1.0.0!
+        .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
 
-        try {
+        try
+        {
             m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
             fail("Succeeded into installing fix package for undefined target package?!");
         }
-        catch (DeploymentException exception) {
+        catch (DeploymentException exception)
+        {
             // Ok; expected
             assertDeploymentException(CODE_MISSING_FIXPACK_TARGET, exception);
         }
@@ -151,18 +149,18 @@
      * Tests that a fix package can only be installed after at least one version of the denoted target package is installed.
      */
     @Test
-    public void testInstallFixPackageWithoutTargetFail() throws Exception {
+    public void testInstallFixPackageWithoutTargetFail() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
-        try {
+        try
+        {
             m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
             fail("Should not be able to install fix package without target?!");
         }
-        catch (DeploymentException exception) {
+        catch (DeploymentException exception)
+        {
             // Ok; expected
             assertDeploymentException(CODE_MISSING_FIXPACK_TARGET, exception);
         }
@@ -172,10 +170,10 @@
      * Tests that installing a fix-package causes the original target package to be replaced.
      */
     @Test
-    public void testInstallFixPackageReplacesOriginalTargetPackageOk() throws Exception {
+    public void testInstallFixPackageReplacesOriginalTargetPackageOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -185,10 +183,7 @@
         awaitRefreshPackagesEvent();
 
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
 
         DeploymentPackage dp2 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp2);
@@ -202,11 +197,11 @@
      * Tests that installing a fix-package that mentions a bundle that is not in the target package fails.
      */
     @Test
-    public void testInstallFixPackageWithMissingTargetBundleFail() throws Exception {
+    public void testInstallFixPackageWithMissingTargetBundleFail() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
         // missed valid-bundle1 as dependency...
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -216,16 +211,15 @@
         awaitRefreshPackagesEvent();
 
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle3")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle3"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
 
-        try {
+        try
+        {
             m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
             fail("Succeeded into installing a fix-package with a missing bundle on target?!");
         }
-        catch (DeploymentException exception) {
+        catch (DeploymentException exception)
+        {
             assertDeploymentException(CODE_MISSING_BUNDLE, exception);
         }
     }
@@ -234,10 +228,10 @@
      * Tests that installing a fix-package that mentions a resource that is not in the target package fails.
      */
     @Test
-    public void testInstallFixPackageWithMissingTargetResourceFail() throws Exception {
+    public void testInstallFixPackageWithMissingTargetResourceFail() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -247,16 +241,16 @@
         awaitRefreshPackagesEvent();
 
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createResourceProcessorResource().setUrl(getTestBundle("rp1")))
-            .add(dpBuilder.createResource().setResourceProcessorPID(TEST_FAILING_BUNDLE_RP1).setUrl(getTestResource("test-config1.xml")).setMissing());
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createResourceProcessorResource().setUrl(getTestBundle("rp1"))).add(
+            dpBuilder.createResource().setResourceProcessorPID(TEST_FAILING_BUNDLE_RP1).setUrl(getTestResource("test-config1.xml")).setMissing());
 
-        try {
+        try
+        {
             m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
             fail("Succeeded into installing a fix-package with a missing bundle on target?!");
         }
-        catch (DeploymentException exception) {
+        catch (DeploymentException exception)
+        {
             assertDeploymentException(CODE_MISSING_RESOURCE, exception);
         }
     }
@@ -265,10 +259,10 @@
      * Tests that installing a fix-package that mentions a resource processor that is not in the target package fails.
      */
     @Test
-    public void testInstallFixPackageWithMissingTargetResourceProcessorFail() throws Exception {
+    public void testInstallFixPackageWithMissingTargetResourceProcessorFail() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -278,16 +272,16 @@
         awaitRefreshPackagesEvent();
 
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createResourceProcessorResource().setUrl(getTestBundle("rp1")).setMissing())
-            .add(dpBuilder.createResource().setResourceProcessorPID(TEST_FAILING_BUNDLE_RP1).setUrl(getTestResource("test-config1.xml")));
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createResourceProcessorResource().setUrl(getTestBundle("rp1")).setMissing()).add(
+            dpBuilder.createResource().setResourceProcessorPID(TEST_FAILING_BUNDLE_RP1).setUrl(getTestResource("test-config1.xml")));
 
-        try {
+        try
+        {
             m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
             fail("Succeeded into installing a fix-package with a missing bundle on target?!");
         }
-        catch (DeploymentException exception) {
+        catch (DeploymentException exception)
+        {
             assertDeploymentException(CODE_MISSING_BUNDLE, exception);
         }
     }
@@ -296,10 +290,10 @@
      * Tests that installing a fix-package that mentions a bundle that does exist (in another DP), but is not in the target package fails.
      */
     @Test
-    public void testInstallFixPackageWithMissingTargetBundleFromOtherPackageFail() throws Exception {
+    public void testInstallFixPackageWithMissingTargetBundleFromOtherPackageFail() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -309,8 +303,7 @@
         assertEquals("Expected only a single deployment package?!", 1, m_deploymentAdmin.listDeploymentPackages().length);
 
         dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp2 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp2);
@@ -320,16 +313,15 @@
         assertEquals("Expected only a single deployment package?!", 2, m_deploymentAdmin.listDeploymentPackages().length);
 
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")).setMissing())
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle3")));
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")).setMissing()).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle3")));
 
-        try {
+        try
+        {
             m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
             fail("Succeeded into installing a fix-package with a missing bundle on target?!");
         }
-        catch (DeploymentException exception) {
+        catch (DeploymentException exception)
+        {
             assertDeploymentException(CODE_BUNDLE_SHARING_VIOLATION, exception);
         }
     }
@@ -338,10 +330,10 @@
      * Tests that only in a fix-package bundle can be marked as missing.
      */
     @Test
-    public void testMissingBundlesOnlyInFixPackageFail() throws Exception {
+    public void testMissingBundlesOnlyInFixPackageFail() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -354,16 +346,15 @@
         assertEquals(Bundle.INSTALLED, bundle.getState());
 
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .disableVerification()
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
+        dpBuilder.disableVerification().add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
 
-        try {
+        try
+        {
             m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
             fail("Failed to install missing bundle?!");
         }
-        catch (DeploymentException exception) {
+        catch (DeploymentException exception)
+        {
             // Ok; expected...
             assertEquals("Invalid exception code?!", CODE_BAD_HEADER, exception.getCode());
         }
@@ -373,11 +364,10 @@
      * Tests the removal of a bundle through a fix package.
      */
     @Test
-    public void testRemoveBundleInFixPackageUpdateOk() throws Exception {
+    public void testRemoveBundleInFixPackageUpdateOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -391,9 +381,7 @@
 
         // valid-bundle2 is to be removed by this fix package...
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")).setMissing());
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")).setMissing());
 
         DeploymentPackage dp2 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp2);
@@ -408,10 +396,10 @@
      * Tests that we can uninstall a fix-package.
      */
     @Test
-    public void testUninstallBundleAddedInFixPackageOk() throws Exception {
+    public void testUninstallBundleAddedInFixPackageOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -420,10 +408,7 @@
 
         // Add valid-bundle1 through fix-package...
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
 
         DeploymentPackage dp2 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp2);
@@ -451,11 +436,10 @@
      * Tests that we can uninstall a fix-package.
      */
     @Test
-    public void testUninstallBundleRemovedInFixPackageOk() throws Exception {
+    public void testUninstallBundleRemovedInFixPackageOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -464,9 +448,7 @@
 
         // remove valid-bundle1 through fix package...
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
 
         DeploymentPackage dp2 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp2);
@@ -494,10 +476,10 @@
      * Tests that we can uninstall a fix-package and that this will only uninstall the bundles installed by the fix-package.
      */
     @Test
-    public void testUninstallFixPackageOnlyRemovesOwnArtifactsOk() throws Exception {
+    public void testUninstallFixPackageOnlyRemovesOwnArtifactsOk() throws Exception
+    {
         DeploymentPackageBuilder dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle1")));
 
         DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp1);
@@ -505,8 +487,7 @@
         assertEquals("Expected a single deployment package?!", 1, m_deploymentAdmin.listDeploymentPackages().length);
 
         dpBuilder = createNewDeploymentPackageBuilder("1.0.0");
-        dpBuilder
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")));
 
         DeploymentPackage dp2 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp2);
@@ -517,10 +498,7 @@
 
         // add bundle2 through fix package...
         dpBuilder = createDeploymentPackageBuilder(dpBuilder.getSymbolicName(), "1.0.1");
-        dpBuilder
-            .setFixPackage("[1.0,2.0)")
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle3")))
-            .add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
+        dpBuilder.setFixPackage("[1.0,2.0)").add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle3"))).add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundle2")).setMissing());
 
         DeploymentPackage dp3 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
         assertNotNull("No deployment package returned?!", dp3);
@@ -546,14 +524,15 @@
         // The bundle installed in another deployment package should still remain...
         assertBundleExists(getSymbolicName("bundle1"), "1.0.0");
     }
-    
-    @Test
-    public void testInstallAndUpdateImplementationBundleWithSeparateAPIBundle_FELIX4184() throws Exception {
-    	String value = System.getProperty("org.apache.felix.deploymentadmin.stopunaffectedbundle");
-    	System.setProperty("org.apache.felix.deploymentadmin.stopunaffectedbundle", "false");
-    	// first, install a deployment package with implementation and api bundles in version 1.0.0
 
-    	DeploymentPackageBuilder dpBuilder = createDeploymentPackageBuilder("a", "1.0.0");
+    @Test
+    public void testInstallAndUpdateImplementationBundleWithSeparateAPIBundle_FELIX4184() throws Exception
+    {
+        String value = System.getProperty("org.apache.felix.deploymentadmin.stopunaffectedbundle");
+        System.setProperty("org.apache.felix.deploymentadmin.stopunaffectedbundle", "false");
+        // first, install a deployment package with implementation and api bundles in version 1.0.0
+
+        DeploymentPackageBuilder dpBuilder = createDeploymentPackageBuilder("a", "1.0.0");
         dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundleimpl1", "bundleimpl", "1.0.0")));
         dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundleapi1", "bundleapi", "1.0.0")));
 
@@ -576,8 +555,49 @@
         assertBundleExists(getSymbolicName("bundleapi"), "2.0.0");
         assertBundleNotExists(getSymbolicName("bundleimpl"), "1.0.0");
         assertBundleNotExists(getSymbolicName("bundleapi"), "1.0.0");
-        if (value != null) {
-        	System.setProperty("org.apache.felix.deploymentadmin.stopunaffectedbundle", value);
+        if (value != null)
+        {
+            System.setProperty("org.apache.felix.deploymentadmin.stopunaffectedbundle", value);
         }
     }
+
+    /**
+     * Tests that if we try to update with a DP containing a duplicate bundle (of which one is already installed in 
+     * an earlier DP) that this will fail the installation. See FELIX-4463.
+     */
+    @Test
+    public void testUpdateWithDuplicateBundleFail() throws Exception
+    {
+        DeploymentPackageBuilder dpBuilder = createDeploymentPackageBuilder("c", "1.0.0");
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundleimpl1", "bundleimpl", "1.0.0")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundleapi1", "bundleapi", "1.0.0")));
+
+        // Should succeed, as the DP is correct... 
+        DeploymentPackage dp1 = m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
+        assertNotNull("No deployment package returned?!", dp1);
+
+        // then, install a fix package with implementation and api bundles in version 2.0.0, but *also* containing the original implementation 
+        // bundle, which is incorrect (no bundles with the same BSN may exist in a DP)...
+        dpBuilder = createDeploymentPackageBuilder("c", "2.0.0").setFixPackage("[1.0.0,2.0.0]");
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundleapi1", "bundleapi", "1.0.0")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundleimpl2", "bundleimpl", "2.0.0")));
+        dpBuilder.add(dpBuilder.createBundleResource().setUrl(getTestBundle("bundleimpl1", "bundleimpl", "1.0.0")));
+
+        try
+        {
+            m_deploymentAdmin.installDeploymentPackage(dpBuilder.generate());
+            fail("DeploymentException expected!");
+        }
+        catch (DeploymentException e)
+        {
+            // Ok; expected...
+            assertEquals(DeploymentException.CODE_OTHER_ERROR, e.getCode());
+        }
+
+        awaitRefreshPackagesEvent();
+
+        // Nothing should be updated...
+        assertBundleExists(getSymbolicName("bundleimpl"), "1.0.0");
+        assertBundleExists(getSymbolicName("bundleapi"), "1.0.0");
+    }
 }