felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject svn commit: r1352090 [1/3] - in /felix/trunk/deploymentadmin: ./ deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/ deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ itest/ itest/src/ itest/src/test/ itest/src/test/java/ ...
Date Wed, 20 Jun 2012 13:27:05 GMT
Author: marrs
Date: Wed Jun 20 13:27:02 2012
New Revision: 1352090

URL: http://svn.apache.org/viewvc?rev=1352090&view=rev
Log:
Added a whole collection of tests to ensure that DeploymentAdmin conforms to the specification and works correctly. Refactored some of the code. Specifically modified the uninstall behavior to make it spec compliant.

Added:
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllBundlesCommand.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllResourcesCommand.java
    felix/trunk/deploymentadmin/itest/
    felix/trunk/deploymentadmin/itest/pom.xml
    felix/trunk/deploymentadmin/itest/src/
    felix/trunk/deploymentadmin/itest/src/test/
    felix/trunk/deploymentadmin/itest/src/test/java/
    felix/trunk/deploymentadmin/itest/src/test/java/org/
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/BaseIntegrationTest.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/CustomizerTest.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/DeploymentAdminTest.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/DeploymentPackageBuilderTest.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallDeploymentPackageTest.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/InstallFixPackageTest.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/ResourceSharingTest.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/UninstallDeploymentPackageTest.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/util/
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/util/ArtifactData.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/util/ArtifactDataBuilder.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/util/BundleDataBuilder.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/util/DeploymentPackageBuilder.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/util/ResourceDataBuilder.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/util/ResourceFilter.java
    felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/util/ResourceProcessorDataBuilder.java
    felix/trunk/deploymentadmin/itest/src/test/resources/
    felix/trunk/deploymentadmin/itest/src/test/resources/logback.xml
    felix/trunk/deploymentadmin/itest/src/test/resources/test-config1.xml
    felix/trunk/deploymentadmin/testbundles/
    felix/trunk/deploymentadmin/testbundles/bundle1/
    felix/trunk/deploymentadmin/testbundles/bundle1/bnd.bnd
    felix/trunk/deploymentadmin/testbundles/bundle1/pom.xml
    felix/trunk/deploymentadmin/testbundles/bundle1/src/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/apache/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/apache/felix/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/apache/felix/deploymentadmin/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/apache/felix/deploymentadmin/test/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/apache/felix/deploymentadmin/test/bundle1/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/apache/felix/deploymentadmin/test/bundle1/TestService.java
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/apache/felix/deploymentadmin/test/bundle1/impl/
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/apache/felix/deploymentadmin/test/bundle1/impl/Activator.java
    felix/trunk/deploymentadmin/testbundles/bundle1/src/main/java/org/apache/felix/deploymentadmin/test/bundle1/impl/TestServiceImpl.java
    felix/trunk/deploymentadmin/testbundles/bundle2/
    felix/trunk/deploymentadmin/testbundles/bundle2/bnd.bnd
    felix/trunk/deploymentadmin/testbundles/bundle2/pom.xml
    felix/trunk/deploymentadmin/testbundles/bundle2/src/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/java/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/java/org/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/java/org/apache/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/java/org/apache/felix/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/java/org/apache/felix/deploymentadmin/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/java/org/apache/felix/deploymentadmin/test/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/java/org/apache/felix/deploymentadmin/test/bundle2/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/java/org/apache/felix/deploymentadmin/test/bundle2/impl/
    felix/trunk/deploymentadmin/testbundles/bundle2/src/main/java/org/apache/felix/deploymentadmin/test/bundle2/impl/Activator.java
    felix/trunk/deploymentadmin/testbundles/bundle3/
    felix/trunk/deploymentadmin/testbundles/bundle3/bnd.bnd
    felix/trunk/deploymentadmin/testbundles/bundle3/pom.xml
    felix/trunk/deploymentadmin/testbundles/bundle3/src/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/java/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/java/org/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/java/org/apache/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/java/org/apache/felix/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/java/org/apache/felix/deploymentadmin/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/java/org/apache/felix/deploymentadmin/test/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/java/org/apache/felix/deploymentadmin/test/bundle3/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/java/org/apache/felix/deploymentadmin/test/bundle3/impl/
    felix/trunk/deploymentadmin/testbundles/bundle3/src/main/java/org/apache/felix/deploymentadmin/test/bundle3/impl/Activator.java
    felix/trunk/deploymentadmin/testbundles/pom.xml
    felix/trunk/deploymentadmin/testbundles/rp1/
    felix/trunk/deploymentadmin/testbundles/rp1/bnd.bnd
    felix/trunk/deploymentadmin/testbundles/rp1/pom.xml
    felix/trunk/deploymentadmin/testbundles/rp1/src/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/java/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/java/org/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/java/org/apache/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/java/org/apache/felix/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/java/org/apache/felix/deploymentadmin/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/java/org/apache/felix/deploymentadmin/test/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/java/org/apache/felix/deploymentadmin/test/rp1/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/java/org/apache/felix/deploymentadmin/test/rp1/impl/
    felix/trunk/deploymentadmin/testbundles/rp1/src/main/java/org/apache/felix/deploymentadmin/test/rp1/impl/Activator.java
    felix/trunk/deploymentadmin/testbundles/rp2/
    felix/trunk/deploymentadmin/testbundles/rp2/bnd.bnd
    felix/trunk/deploymentadmin/testbundles/rp2/pom.xml
    felix/trunk/deploymentadmin/testbundles/rp2/src/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/java/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/java/org/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/java/org/apache/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/java/org/apache/felix/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/java/org/apache/felix/deploymentadmin/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/java/org/apache/felix/deploymentadmin/test/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/java/org/apache/felix/deploymentadmin/test/rp2/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/java/org/apache/felix/deploymentadmin/test/rp2/impl/
    felix/trunk/deploymentadmin/testbundles/rp2/src/main/java/org/apache/felix/deploymentadmin/test/rp2/impl/Activator.java
Modified:
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Constants.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Utils.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/CommitResourceCommand.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DeploymentSessionImpl.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ProcessResourceCommand.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java
    felix/trunk/deploymentadmin/pom.xml

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java?rev=1352090&r1=1352089&r2=1352090&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java Wed Jun 20 13:27:02 2012
@@ -146,10 +146,14 @@ public abstract class AbstractDeployment
         if (isStale()) {
             throw new IllegalStateException("Can not get bundle from stale deployment package.");
         }
-        if (m_nameToBundleInfo.containsKey(symbolicName)) {
+        
+        BundleInfo bundleInfo = (BundleInfo) m_nameToBundleInfo.get(symbolicName);
+        if (bundleInfo != null) {
+            Version version = bundleInfo.getVersion();
+
             Bundle[] bundles = m_bundleContext.getBundles();
             for (int i = 0; i < bundles.length; i++) {
-                if (symbolicName.equals(bundles[i].getSymbolicName())) {
+                if (symbolicName.equals(bundles[i].getSymbolicName()) && version.equals(bundles[i].getVersion())) {
                     return bundles[i];
                 }
             }
@@ -272,6 +276,14 @@ public abstract class AbstractDeployment
         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.
+     */
+    public boolean isNew() {
+        return this == EMPTY_PACKAGE;
+    }
+    
     public void setStale(boolean isStale) {
         m_isStale = isStale;
     }
@@ -280,12 +292,23 @@ public abstract class AbstractDeployment
         if (isStale()) {
             throw new IllegalStateException("Deployment package is stale, cannot uninstall.");
         }
-        m_deploymentAdmin.uninstallDeploymentPackage(this);
-        setStale(true);
+        try {
+            m_deploymentAdmin.uninstallDeploymentPackage(this, false /* force */);
+        } finally {
+            setStale(true);
+        }
     }
 
     public boolean uninstallForced() throws DeploymentException {
-        throw new IllegalStateException("Not implemented, use uninstall() for now.");
+        if (isStale()) {
+            throw new IllegalStateException("Deployment package is stale, cannot uninstall.");
+        }
+        try {
+            m_deploymentAdmin.uninstallDeploymentPackage(this, true /* force */);
+        } finally {
+            setStale(true);
+        }
+        return true;
     }
 
     /**

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Constants.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Constants.java?rev=1352090&r1=1352089&r2=1352090&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Constants.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Constants.java Wed Jun 20 13:27:02 2012
@@ -18,6 +18,8 @@
  */
 package org.apache.felix.deploymentadmin;
 
+import org.osgi.service.deploymentadmin.DeploymentPackage;
+
 public interface Constants extends org.osgi.framework.Constants {
 
     // manifest main attribute header constants
@@ -34,7 +36,11 @@ public interface Constants extends org.o
     public static final String EVENTTOPIC_INSTALL = "org/osgi/service/deployment/INSTALL";
     public static final String EVENTTOPIC_UNINSTALL = "org/osgi/service/deployment/UNINSTALL";
     public static final String EVENTTOPIC_COMPLETE = "org/osgi/service/deployment/COMPLETE";
-    public static final String EVENTPROPERTY_DEPLOYMENTPACKAGE_NAME = "deploymentpackage.name";
+    
+    public static final String EVENTPROPERTY_DEPLOYMENTPACKAGE_NAME = DeploymentPackage.EVENT_DEPLOYMENTPACKAGE_NAME;
+    public static final String EVENTPROPERTY_DEPLOYMENTPACKAGE_READABLENAME = DeploymentPackage.EVENT_DEPLOYMENTPACKAGE_READABLENAME;
+    public static final String EVENTPROPERTY_DEPLOYMENTPACKAGE_CURRENTVERSION = DeploymentPackage.EVENT_DEPLOYMENTPACKAGE_CURRENTVERSION;
+    public static final String EVENTPROPERTY_DEPLOYMENTPACKAGE_NEXTVERSION = DeploymentPackage.EVENT_DEPLOYMENTPACKAGE_NEXTVERSION;
     public static final String EVENTPROPERTY_SUCCESSFUL = "successful";
 
     // miscellaneous constants

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java?rev=1352090&r1=1352089&r2=1352090&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java Wed Jun 20 13:27:02 2012
@@ -22,10 +22,10 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Dictionary;
 import java.util.HashMap;
-import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -34,6 +34,8 @@ import java.util.jar.JarInputStream;
 
 import org.apache.felix.deploymentadmin.spi.CommitResourceCommand;
 import org.apache.felix.deploymentadmin.spi.DeploymentSessionImpl;
+import org.apache.felix.deploymentadmin.spi.DropAllBundlesCommand;
+import org.apache.felix.deploymentadmin.spi.DropAllResourcesCommand;
 import org.apache.felix.deploymentadmin.spi.DropBundleCommand;
 import org.apache.felix.deploymentadmin.spi.DropResourceCommand;
 import org.apache.felix.deploymentadmin.spi.GetStorageAreaCommand;
@@ -45,6 +47,7 @@ import org.apache.felix.deploymentadmin.
 import org.apache.felix.deploymentadmin.spi.UpdateCommand;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Version;
 import org.osgi.service.deploymentadmin.DeploymentAdmin;
 import org.osgi.service.deploymentadmin.DeploymentException;
 import org.osgi.service.deploymentadmin.DeploymentPackage;
@@ -70,54 +73,12 @@ public class DeploymentAdminImpl impleme
     private volatile LogService m_log;              /* will be injected by dependencymanager */
     private volatile DeploymentSessionImpl m_session = null;
     private final Map m_packages = new HashMap();
-    private final List m_commandChain = new ArrayList();
     private final Semaphore m_semaphore = new Semaphore();
 
     /**
      * Create new instance of this <code>DeploymentAdmin</code>.
      */
     public DeploymentAdminImpl() {
-        GetStorageAreaCommand getStorageAreaCommand = new GetStorageAreaCommand();
-        m_commandChain.add(getStorageAreaCommand);
-        m_commandChain.add(new StopBundleCommand());
-        m_commandChain.add(new SnapshotCommand(getStorageAreaCommand));
-        m_commandChain.add(new UpdateCommand());
-        m_commandChain.add(new StartCustomizerCommand());
-        CommitResourceCommand commitCommand = new CommitResourceCommand();
-        m_commandChain.add(new ProcessResourceCommand(commitCommand));
-        m_commandChain.add(new DropResourceCommand(commitCommand));
-        m_commandChain.add(new DropBundleCommand());
-        m_commandChain.add(commitCommand);
-        m_commandChain.add(new StartBundleCommand());
-    }
-
-    // called automatically once dependencies are satisfied
-    public void start() throws DeploymentException {
-        File packageDir = m_context.getDataFile(PACKAGE_DIR);
-        if (packageDir == null) {
-            throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Could not create directories needed for deployment package persistence");
-        } else {
-            packageDir.mkdirs();
-            File[] packages = packageDir.listFiles();
-            for(int i = 0; i < packages.length; i++) {
-                if (packages[i].isDirectory()) {
-                    try {
-                        File index = new File(packages[i], PACKAGEINDEX_FILE);
-                        File contents = new File(packages[i], PACKAGECONTENTS_DIR);
-                        FileDeploymentPackage dp = new FileDeploymentPackage(index, contents, m_context, this);
-                        m_packages.put(dp.getName(), dp);
-                    }
-                    catch (IOException e) {
-                        m_log.log(LogService.LOG_WARNING, "Could not read deployment package from disk, skipping: '" + packages[i].getAbsolutePath() + "'");
-                        continue;
-                    }
-                }
-            }
-        }
-    }
-
-    public void stop() {
-    	cancel();
     }
 
     public boolean cancel() {
@@ -129,30 +90,52 @@ public class DeploymentAdminImpl impleme
         return false;
     }
 
-    public DeploymentPackage getDeploymentPackage(String symbName) {
-        if (symbName == null) {
-            throw new IllegalArgumentException("Symbolic name may not be null");
-        }
-        return (DeploymentPackage) m_packages.get(symbName);
+    /**
+     * Returns reference to this bundle's <code>BundleContext</code>
+     *
+     * @return This bundle's <code>BundleContext</code>
+     */
+    public BundleContext getBundleContext() {
+        return m_context;
     }
 
     public DeploymentPackage getDeploymentPackage(Bundle bundle) {
         if (bundle == null) {
             throw new IllegalArgumentException("Bundle can not be null");
         }
-        for (Iterator i = m_packages.values().iterator(); i.hasNext();) {
-            DeploymentPackage dp = (DeploymentPackage) i.next();
-            if (dp.getBundle(bundle.getSymbolicName()) != null) {
-                return dp;
-            }
+        return getDeploymentPackageContainingBundleWithSymbolicName(bundle.getSymbolicName());
+    }
+
+    public DeploymentPackage getDeploymentPackage(String symbName) {
+        if (symbName == null) {
+            throw new IllegalArgumentException("Symbolic name may not be null");
         }
-        return null;
+        return (DeploymentPackage) m_packages.get(symbName);
+    }
+
+    /**
+     * Returns reference to the current logging service defined in the framework.
+     *
+     * @return Currently active <code>LogService</code>.
+     */
+    public LogService getLog() {
+        return m_log;
+    }
+
+    /**
+     * Returns reference to the current package admin defined in the framework.
+     *
+     * @return Currently active <code>PackageAdmin</code>.
+     */
+    public PackageAdmin getPackageAdmin() {
+        return m_packageAdmin;
     }
 
     public DeploymentPackage installDeploymentPackage(InputStream input) throws DeploymentException {
         if (input == null) {
             throw new IllegalArgumentException("Inputstream may not be null");
         }
+
         try {
             if (!m_semaphore.tryAcquire(TIMEOUT)) {
                 throw new DeploymentException(DeploymentException.CODE_TIMEOUT, "Timeout exceeded while waiting to install deployment package (" + TIMEOUT + " ms)");
@@ -164,7 +147,9 @@ public class DeploymentAdminImpl impleme
 
         File tempPackage = null;
         StreamDeploymentPackage source = null;
+        AbstractDeploymentPackage target = null;
         boolean succeeded = false;
+
         try {
             JarInputStream jarInput = null;
             File tempIndex = null;
@@ -184,32 +169,52 @@ public class DeploymentAdminImpl impleme
                 m_log.log(LogService.LOG_ERROR, "Error writing package to disk", e);
                 throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Error writing package to disk", e);
             }
+
             try {
                 jarInput = new JarInputStream(input);
+                
+                if (jarInput.getManifest() == null) {
+                    m_log.log(LogService.LOG_ERROR, "Stream does not contain a valid deployment package: missing manifest!");
+                    throw new DeploymentException(DeploymentException.CODE_MISSING_HEADER, "No manifest present in deployment package!");
+                }
             }
             catch (IOException e) {
                 m_log.log(LogService.LOG_ERROR, "Stream does not contain a valid Jar", e);
                 throw new DeploymentException(DeploymentException.CODE_NOT_A_JAR, "Stream does not contain a valid Jar", e);
             }
+
             source = new StreamDeploymentPackage(jarInput, m_context, this);
-            sendStartedEvent(source.getName());
+            String dpSymbolicName = source.getName();
+            
+            target = getExistingOrEmptyDeploymentPackage(dpSymbolicName);
+            
+            // Fire an event that we're about to install a new package 
+            sendStartedEvent(source, target);
+
+            // Assert that:
+            //   the source has no bundles that exists in other packages than the target.
+            verifyNoResourcesShared(source, target);
             
-            AbstractDeploymentPackage target = (AbstractDeploymentPackage) getDeploymentPackage(source.getName());
-            boolean newPackage = (target == null);
-            if (newPackage) {
-                target = AbstractDeploymentPackage.EMPTY_PACKAGE;
-            }
-            if (source.isFixPackage() && ((newPackage) || (!source.getVersionRange().isInRange(target.getVersion())))) {
-                succeeded = false;
-                m_log.log(LogService.LOG_ERROR, "Target package version '" + target.getVersion() + "' is not in source range '" + source.getVersionRange() + "'");
-                throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Target package version '" + target.getVersion() + "' is not in source range '" + source.getVersionRange() + "'");
+            if (source.isFixPackage()) {
+                // Assert that:
+                //   a. the version of the target matches the required fix-package range;
+                //   b. all missing source bundles are present in the target.
+                verifyFixPackage(source, target);
+            } else {
+                // Assert that:
+                //   no missing resources or bundles are declared.
+                verifySourcePackage(source);
             }
+
+            // To keep track whether or not we're masking an exception during the close of the input stream...
+            boolean installFailed = false;
+            
             try {
-                m_session = new DeploymentSessionImpl(source, target, m_commandChain, this);
-                m_session.call();
+                m_session = new DeploymentSessionImpl(source, target, createInstallCommandChain(), this);
+                m_session.call(false /* ignoreExceptions */);
             }
             catch (DeploymentException de) {
-                succeeded = false;
+                installFailed = true;
                 throw de;
             } finally {
                 try {
@@ -222,57 +227,106 @@ public class DeploymentAdminImpl impleme
                 catch (IOException e) {
                     m_log.log(LogService.LOG_ERROR, "Could not close stream properly", e);
                     // Do not mask out any originally thrown exceptions...
-                    if (succeeded) {
-                        succeeded = false;
+                    if (!installFailed) {
                         throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Could not close stream properly", e);
                     }
                 }
             }
 
-            File targetContents = m_context.getDataFile(PACKAGE_DIR + File.separator + source.getName() + File.separator + PACKAGECONTENTS_DIR);
-            File targetIndex = m_context.getDataFile(PACKAGE_DIR + File.separator + source.getName() + File.separator + PACKAGEINDEX_FILE);
+            String dpInstallBaseDirectory = PACKAGE_DIR + File.separator + dpSymbolicName;
+
+            File targetContents = m_context.getDataFile(dpInstallBaseDirectory + File.separator + PACKAGECONTENTS_DIR);
+            File targetIndex = m_context.getDataFile(dpInstallBaseDirectory + File.separator + PACKAGEINDEX_FILE);
+
             if (source.isFixPackage()) {
                 try {
                     Utils.merge(targetIndex, targetContents, tempIndex, tempContents);
                 }
                 catch (IOException e) {
-                    succeeded = false;
                     m_log.log(LogService.LOG_ERROR, "Could not merge source fix package with target deployment package", e);
                     throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Could not merge source fix package with target deployment package", e);
                 }
             }
             else {
-                File targetPackage = m_context.getDataFile(PACKAGE_DIR + File.separator + source.getName());
+                File targetPackage = m_context.getDataFile(dpInstallBaseDirectory);
                 targetPackage.mkdirs();
                 if (!Utils.replace(targetPackage, tempPackage)) {
                 	throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Could not replace " + targetPackage + " with " + tempPackage);
                 }
             }
+            
             FileDeploymentPackage fileDeploymentPackage = null;
             try {
                 fileDeploymentPackage = new FileDeploymentPackage(targetIndex, targetContents, m_context, this);
-                m_packages.put(source.getName(), fileDeploymentPackage);
+                m_packages.put(dpSymbolicName, fileDeploymentPackage);
             }
             catch (IOException e) {
-                succeeded = false;
                 m_log.log(LogService.LOG_ERROR, "Could not create installed deployment package from disk", e);
                 throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Could not create installed deployment package from disk", e);
             }
+
+            // Since we're here, it means everything went OK, so we might as well raise our success flag...
             succeeded = true;
+
             return fileDeploymentPackage;
         }
         finally {
             if (tempPackage != null) {
-                delete(tempPackage);
+                Utils.delete(tempPackage);
             }
         	if (source != null) {
-        	    sendCompleteEvent(source.getName(), succeeded);
+        	    sendCompleteEvent(source, target, succeeded);
         	}
             m_semaphore.release();
         }
     }
-    
-    public void uninstallDeploymentPackage(DeploymentPackage dp) throws DeploymentException {
+
+	public DeploymentPackage[] listDeploymentPackages() {
+        Collection packages = m_packages.values();
+        return (DeploymentPackage[]) packages.toArray(new DeploymentPackage[packages.size()]);
+    }
+
+    /**
+     * Called by dependency manager upon start of this component.
+     */
+    public void start() throws DeploymentException {
+        File packageDir = m_context.getDataFile(PACKAGE_DIR);
+        if (packageDir == null) {
+            throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Could not create directories needed for deployment package persistence");
+        } else {
+            packageDir.mkdirs();
+            File[] packages = packageDir.listFiles();
+            for(int i = 0; i < packages.length; i++) {
+                if (packages[i].isDirectory()) {
+                    try {
+                        File index = new File(packages[i], PACKAGEINDEX_FILE);
+                        File contents = new File(packages[i], PACKAGECONTENTS_DIR);
+                        FileDeploymentPackage dp = new FileDeploymentPackage(index, contents, m_context, this);
+                        m_packages.put(dp.getName(), dp);
+                    }
+                    catch (IOException e) {
+                        m_log.log(LogService.LOG_WARNING, "Could not read deployment package from disk, skipping: '" + packages[i].getAbsolutePath() + "'");
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Called by dependency manager when stopping this component.
+     */
+    public void stop() {
+    	cancel();
+    }
+
+    /**
+     * Uninstalls the given deployment package from the system.
+     * 
+     * @param dp the deployment package to uninstall, cannot be <code>null</code>;
+     * @param forced <code>true</code> to force the uninstall, meaning that any exceptions are ignored during the uninstallation.
+     * @throws DeploymentException in case the uninstall failed.
+     */
+    public void uninstallDeploymentPackage(DeploymentPackage dp, boolean forced) throws DeploymentException {
         try {
             if (!m_semaphore.tryAcquire(TIMEOUT)) {
                 throw new DeploymentException(DeploymentException.CODE_TIMEOUT, "Timeout exceeded while waiting to uninstall deployment package (" + TIMEOUT + " ms)");
@@ -281,87 +335,276 @@ public class DeploymentAdminImpl impleme
         catch (InterruptedException ie) {
             throw new DeploymentException(DeploymentException.CODE_TIMEOUT, "Thread interrupted");
         }
+        
         boolean succeeded = false;
         AbstractDeploymentPackage source = AbstractDeploymentPackage.EMPTY_PACKAGE;
         AbstractDeploymentPackage target = (AbstractDeploymentPackage) dp;
+
+        // Notify listeners that we've about to uninstall the deployment package...
+        sendUninstallEvent(source, target);
+
         try {
             try {
-                m_session = new DeploymentSessionImpl(source, target, m_commandChain, this);
-                m_session.call();
+                m_session = new DeploymentSessionImpl(source, target, createUninstallCommandChain(), this);
+                m_session.call(forced /* ignoreExceptions */);
             }
             catch (DeploymentException de) {
-                succeeded = false;
                 throw de;
             }
 
             File targetPackage = m_context.getDataFile(PACKAGE_DIR + File.separator + source.getName());
-            delete(targetPackage);
+            Utils.delete(targetPackage);
+            
             m_packages.remove(dp.getName());
+
             succeeded = true;
         }
         finally {
             if (source != null) {
-                sendCompleteEvent(source.getName(), succeeded);
+                sendCompleteEvent(source, target, succeeded);
             }
             m_semaphore.release();
         }
     }
+    
+    private List createInstallCommandChain() {
+        List commandChain = new ArrayList();
+
+        GetStorageAreaCommand getStorageAreaCommand = new GetStorageAreaCommand();
+        commandChain.add(getStorageAreaCommand);
+        commandChain.add(new StopBundleCommand());
+        commandChain.add(new SnapshotCommand(getStorageAreaCommand));
+        commandChain.add(new UpdateCommand());
+        commandChain.add(new StartCustomizerCommand());
+        CommitResourceCommand commitCommand = new CommitResourceCommand();
+        commandChain.add(new ProcessResourceCommand(commitCommand));
+        commandChain.add(new DropResourceCommand(commitCommand));
+        commandChain.add(new DropBundleCommand());
+        commandChain.add(commitCommand);
+        commandChain.add(new StartBundleCommand());
+        
+        return commandChain;
+    }
+    
+    private List createUninstallCommandChain() {
+        List commandChain = new ArrayList();
+
+        GetStorageAreaCommand getStorageAreaCommand = new GetStorageAreaCommand();
+        commandChain.add(getStorageAreaCommand);
+        commandChain.add(new StopBundleCommand());
+        commandChain.add(new SnapshotCommand(getStorageAreaCommand));
+        commandChain.add(new StartCustomizerCommand());
+        CommitResourceCommand commitCommand = new CommitResourceCommand();
+        commandChain.add(new DropAllResourcesCommand(commitCommand));
+        commandChain.add(commitCommand);
+        commandChain.add(new DropAllBundlesCommand());
+        
+        return commandChain;
+    }
+
+    /**
+     * Creates the properties for a new event.
+     * 
+     * @param source the source package being installed;
+     * @param target the current installed package (can be new).
+     * @return the event properties, never <code>null</code>.
+     */
+    private Dictionary createEventProperties(AbstractDeploymentPackage source, AbstractDeploymentPackage target) {
+        Dictionary props = new Properties();
+        if (source != null) {
+            String displayName = source.getDisplayName();
+            if (displayName == null) {
+                displayName = source.getName();
+            }
 
-    private void delete(File target) {
-    	if (target.isDirectory()) {
-            File[] childs = target.listFiles();
-            for (int i = 0; i < childs.length; i++) {
-                delete(childs[i]);
+            props.put(Constants.EVENTPROPERTY_DEPLOYMENTPACKAGE_NAME, source.getName());
+            props.put(Constants.EVENTPROPERTY_DEPLOYMENTPACKAGE_READABLENAME, displayName);
+            if (!source.isNew()) {
+                props.put(Constants.EVENTPROPERTY_DEPLOYMENTPACKAGE_NEXTVERSION, source.getVersion());
             }
         }
-    	target.delete();
-	}
+        if ((target != null) && !target.isNew()) {
+            props.put(Constants.EVENTPROPERTY_DEPLOYMENTPACKAGE_CURRENTVERSION, target.getVersion());
+        }
+        return props;
+    }
+    
+    /**
+     * Searches for a deployment package that contains a bundle with the given symbolic name.
+     * 
+     * @param symbolicName the symbolic name of the <em>bundle</em> to return the containing deployment package for, cannot be <code>null</code>.
+     * @return the deployment package containing the given bundle, or <code>null</code> if no deployment package contained such bundle.
+     */
+    private DeploymentPackage getDeploymentPackageContainingBundleWithSymbolicName(String symbolicName) {
+        for (Iterator i = m_packages.values().iterator(); i.hasNext();) {
+            DeploymentPackage dp = (DeploymentPackage) i.next();
+            if (dp.getBundle(symbolicName) != null) {
+                return dp;
+            }
+        }
+        return null;
+    }
 
-	public DeploymentPackage[] listDeploymentPackages() {
-        Collection packages = m_packages.values();
-        return (DeploymentPackage[]) packages.toArray(new DeploymentPackage[packages.size()]);
+    /**
+     * Returns either an existing deployment package, or if no such package exists, an empty package.
+     * 
+     * @param symbolicName the name of the deployment package to retrieve, cannot be <code>null</code>.
+     * @return a deployment package, never <code>null</code>.
+     */
+    private AbstractDeploymentPackage getExistingOrEmptyDeploymentPackage(String symbolicName) {
+        AbstractDeploymentPackage result = (AbstractDeploymentPackage) getDeploymentPackage(symbolicName);
+        if (result == null) {
+            result = AbstractDeploymentPackage.EMPTY_PACKAGE;
+        }
+        return result;
     }
 
     /**
-     * Returns reference to this bundle's <code>BundleContext</code>
-     *
-     * @return This bundle's <code>BundleContext</code>
+     * Returns all bundles that are not present in any deployment package. Ultimately, this should only 
+     * be one bundle, the system bundle, but this is not enforced in any way by the specification.
+     * 
+     * @return an array of non-deployment packaged bundles, never <code>null</code>.
      */
-    public BundleContext getBundleContext() {
-        return m_context;
+    private Bundle[] getNonDeploymentPackagedBundles() {
+        List result = new ArrayList(Arrays.asList(m_context.getBundles()));
+        
+        Iterator iter = result.iterator();
+        while (iter.hasNext()) {
+            Bundle suspect = (Bundle) iter.next();
+            if (suspect.getLocation().startsWith(Constants.BUNDLE_LOCATION_PREFIX)) {
+                iter.remove();
+            }
+        }
+
+        return (Bundle[]) result.toArray(new Bundle[result.size()]);
     }
 
     /**
-     * Returns reference to the current logging service defined in the framework.
-     *
-     * @return Currently active <code>LogService</code>.
+     * Sends out an event that the {@link #installDeploymentPackage(InputStream)} is 
+     * completed its installation of a deployment package.
+     * 
+     * @param source the source package being installed;
+     * @param target the current installed package (can be new);
+     * @param success <code>true</code> if the installation was successful, <code>false</code> otherwise.
      */
-    public LogService getLog() {
-        return m_log;
+    private void sendCompleteEvent(AbstractDeploymentPackage source, AbstractDeploymentPackage target, boolean success) {
+        Dictionary props = createEventProperties(source, target);
+        props.put(Constants.EVENTPROPERTY_SUCCESSFUL, Boolean.valueOf(success));
+        
+        m_eventAdmin.postEvent(new Event(Constants.EVENTTOPIC_COMPLETE, props));
     }
 
     /**
-     * Returns reference to the current package admin defined in the framework.
-     *
-     * @return Currently active <code>PackageAdmin</code>.
+     * Sends out an event that the {@link #installDeploymentPackage(InputStream)} is about 
+     * to install a new deployment package.
+     * 
+     * @param source the source package being installed;
+     * @param target the current installed package (can be new).
      */
-    public PackageAdmin getPackageAdmin() {
-        return m_packageAdmin;
+    private void sendStartedEvent(AbstractDeploymentPackage source, AbstractDeploymentPackage target) {
+        Dictionary props = createEventProperties(source, target);
+
+        m_eventAdmin.postEvent(new Event(Constants.EVENTTOPIC_INSTALL, props));
     }
 
-    private void sendStartedEvent(String name) {
-        Dictionary props = new Properties();
-        props.put(Constants.EVENTPROPERTY_DEPLOYMENTPACKAGE_NAME, name);
-        Event completeEvent = new Event(Constants.EVENTTOPIC_INSTALL, props);
-        m_eventAdmin.postEvent(completeEvent);
+    /**
+     * Sends out an event that the {@link #uninstallDeploymentPackage(DeploymentPackage)} is about 
+     * to uninstall a deployment package.
+     * 
+     * @param source the source package being uninstalled;
+     * @param target the current installed package (can be new).
+     */
+    private void sendUninstallEvent(AbstractDeploymentPackage source, AbstractDeploymentPackage target) {
+        Dictionary props = createEventProperties(source, target);
+
+        m_eventAdmin.postEvent(new Event(Constants.EVENTTOPIC_UNINSTALL, props));
     }
 
-    private void sendCompleteEvent(String name, boolean success) {
-        Dictionary props = new Hashtable();
-        props.put(Constants.EVENTPROPERTY_DEPLOYMENTPACKAGE_NAME, name);
-        props.put(Constants.EVENTPROPERTY_SUCCESSFUL, new Boolean(success));
-        Event completeEvent = new Event(Constants.EVENTTOPIC_COMPLETE, props);
-        m_eventAdmin.postEvent(completeEvent);
+    /**
+     * Verifies that the version of the target matches the required source version range, and 
+     * whether all missing source resources are available in the target.
+     * 
+     * @param source the fix-package source to verify;
+     * @param target the target package to verify against.
+     * @throws DeploymentException in case verification failed.
+     */
+    private void verifyFixPackage(AbstractDeploymentPackage source, AbstractDeploymentPackage target) throws DeploymentException {
+        boolean newPackage = target.isNew();
+
+        // Verify whether the target package exists, and if so, falls in the requested fix-package range...
+        if (newPackage || (!source.getVersionRange().isInRange(target.getVersion()))) {
+            m_log.log(LogService.LOG_ERROR, "Target package version '" + target.getVersion() + "' is not in source range '" + source.getVersionRange() + "'");
+            throw new DeploymentException(DeploymentException.CODE_MISSING_FIXPACK_TARGET, "Target package version '" + target.getVersion() + "' is not in source range '" + source.getVersionRange() + "'");
+        }
+
+        // Verify whether all missing bundles are available in the target package...
+        BundleInfoImpl[] bundleInfos = source.getBundleInfoImpls();
+        for (int i = 0; i < bundleInfos.length; i++) {
+            if (bundleInfos[i].isMissing()) {
+                // Check whether the bundle exists in the target package...
+                BundleInfoImpl targetBundleInfo = target.getBundleInfoByPath(bundleInfos[i].getPath());
+                if (targetBundleInfo == null) {
+                    m_log.log(LogService.LOG_ERROR, "Missing bundle '" + bundleInfos[i].getSymbolicName() + "/" + bundleInfos[i].getVersion() + " does not exist in target package!");
+                    throw new DeploymentException(DeploymentException.CODE_MISSING_BUNDLE, "Missing bundle '" + bundleInfos[i].getSymbolicName() + "/" + bundleInfos[i].getVersion() + " does not exist in target package!");
+                }
+            }
+        }
+
+        // Verify whether all missing resources are available in the target package...
+        ResourceInfoImpl[] resourceInfos = source.getResourceInfos();
+        for (int i = 0; i < resourceInfos.length; i++) {
+            if (resourceInfos[i].isMissing()) {
+                // Check whether the resource exists in the target package...
+                ResourceInfoImpl targetResourceInfo = target.getResourceInfoByPath(resourceInfos[i].getPath());
+                if (targetResourceInfo == null) {
+                    m_log.log(LogService.LOG_ERROR, "Missing resource '" + resourceInfos[i].getPath() + " does not exist in target package!");
+                    throw new DeploymentException(DeploymentException.CODE_MISSING_RESOURCE, "Missing resource '" + resourceInfos[i].getPath() + " does not exist in target package!");
+                }
+            }
+        }
+    }
+
+    /**
+     * Verifies whether none of the mentioned resources in the source package are present in 
+     * deployment packages other than the given target.
+     * 
+     * @param source the source package to verify;
+     * @param target the target package to verify against.
+     * @throws DeploymentException in case verification fails.
+     */
+    private void verifyNoResourcesShared(AbstractDeploymentPackage source, AbstractDeploymentPackage target) throws DeploymentException {
+        Bundle[] foreignBundles = getNonDeploymentPackagedBundles();
+        
+        // Verify whether all source bundles are available in the target package or absent...
+        BundleInfoImpl[] bundleInfos = source.getBundleInfoImpls();
+        for (int i = 0; i < bundleInfos.length; i++) {
+            String symbolicName = bundleInfos[i].getSymbolicName();
+            Version version = bundleInfos[i].getVersion();
+
+            DeploymentPackage targetPackage = getDeploymentPackageContainingBundleWithSymbolicName(symbolicName);
+            // If found, it should match the given target DP; not found is also ok...
+            if ((targetPackage != null) && !targetPackage.equals(target)) {
+                m_log.log(LogService.LOG_ERROR, "Bundle '" + symbolicName + "/" + version + " already present in other deployment packages!");
+                throw new DeploymentException(DeploymentException.CODE_BUNDLE_SHARING_VIOLATION, "Bundle '" + symbolicName + "/" + version + " already present in other deployment packages!");
+            }
+            
+            if (targetPackage == null) {
+                // Maybe the bundle is installed without deployment admin...
+                for (int j = 0; j < foreignBundles.length; j++) {
+                    if (symbolicName.equals(foreignBundles[j].getSymbolicName()) && version.equals(foreignBundles[j].getVersion())) {
+                        m_log.log(LogService.LOG_ERROR, "Bundle '" + symbolicName + "/" + version + " already present!");
+                        throw new DeploymentException(DeploymentException.CODE_BUNDLE_SHARING_VIOLATION, "Bundle '" + symbolicName + "/" + version + " already present!");
+                    }
+                }
+            }
+        }
+        
+        // TODO verify other resources as well...
     }
 
+    private void verifySourcePackage(AbstractDeploymentPackage source) throws DeploymentException {
+        // TODO this method should do a X-ref check between DP-manifest and JAR-entries...
+//        m_log.log(LogService.LOG_ERROR, "Missing bundle '" + symbolicName + "/" + bundleInfos[i].getVersion() + " does not exist in target package!");
+//        throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Missing bundle '" + symbolicName + "/" + bundleInfos[i].getVersion() + " is not part of target package!");
+    }
 }
\ No newline at end of file

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Utils.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Utils.java?rev=1352090&r1=1352089&r2=1352090&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Utils.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/Utils.java Wed Jun 20 13:27:02 2012
@@ -106,6 +106,18 @@ public class Utils {
         return result;
     }
 
+
+    public static void delete(File target) {
+        // TODO merge with #delete(File, boolean)?!
+        if (target.isDirectory()) {
+            File[] childs = target.listFiles();
+            for (int i = 0; i < childs.length; i++) {
+                delete(childs[i]);
+            }
+        }
+        target.delete();
+    }
+
     public static boolean rename(File from, File to) {
         if (!from.renameTo(to)) {
             if (copy(from, to)) {

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/CommitResourceCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/CommitResourceCommand.java?rev=1352090&r1=1352089&r2=1352090&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/CommitResourceCommand.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/CommitResourceCommand.java Wed Jun 20 13:27:02 2012
@@ -43,6 +43,14 @@ public class CommitResourceCommand exten
             }
             catch (ResourceProcessorException e) {
                 session.getLog().log(LogService.LOG_ERROR, "Preparing commit for resource processor failed", e);
+                // Check what error code we got...
+                if (e.getCode() == ResourceProcessorException.CODE_PREPARE) {
+                    throw new DeploymentException(DeploymentException.CODE_COMMIT_ERROR, "Preparing commit for resource processor failed!", e);
+                }
+                throw new DeploymentException(e.getCode(), "Preparing commit for resource processor failed!", e);
+            }
+            catch (Exception e) {
+                session.getLog().log(LogService.LOG_ERROR, "Preparing commit for resource processor failed", e);
                 throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Preparing commit for resource processor failed", e);
             }
         }

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DeploymentSessionImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DeploymentSessionImpl.java?rev=1352090&r1=1352089&r2=1352090&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DeploymentSessionImpl.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DeploymentSessionImpl.java Wed Jun 20 13:27:02 2012
@@ -19,7 +19,6 @@
 package org.apache.felix.deploymentadmin.spi;
 
 import java.io.File;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -60,7 +59,7 @@ public class DeploymentSessionImpl imple
      *
      * @throws DeploymentException If the session was canceled (<code>DeploymentException.CODE_CANCELLED</code>) or if one of the commands caused an exception (<code>DeploymentException.*</code>)
      */
-    public void call() throws DeploymentException {
+    public void call(boolean ignoreExceptions) throws DeploymentException {
         List executedCommands = new ArrayList();
         for (Iterator i = m_commands.iterator(); i.hasNext();) {
             if (m_cancelled) {
@@ -74,8 +73,10 @@ public class DeploymentSessionImpl imple
                 m_currentCommand.execute(this);
             }
             catch (DeploymentException de) {
-                rollback(executedCommands);
-                throw de;
+                if (!ignoreExceptions) {
+                    rollback(executedCommands);
+                    throw de;
+                }
             }
         }
         for (Iterator i = m_commands.iterator(); i.hasNext();) {
@@ -117,34 +118,17 @@ public class DeploymentSessionImpl imple
      *     persistent storage area for the bundle
      */
     public File getDataFile(Bundle bundle) {
-        BundleContext context = null;
-        try {
-            // try to find the method in the current class
-            Method getBundleContext = bundle.getClass().getDeclaredMethod("getBundleContext", null);
-            getBundleContext.setAccessible(true);
-            context = (BundleContext) getBundleContext.invoke(bundle, null);
-        }
-        catch (Exception e) {
-            // if we cannot find the method at first, we try again below
-        }
-        if (context == null) {
-            try {
-                // try to find the method in superclasses
-                Method getBundleContext = bundle.getClass().getMethod("getBundleContext", null);
-                getBundleContext.setAccessible(true);
-                context = (BundleContext) getBundleContext.invoke(bundle, null);
-            }
-            catch (Exception e) {
-                // we still can't find the method, we will throw an exception indicating that below
-            }
-        }
         File result = null;
+
+        BundleContext context = bundle.getBundleContext();
         if (context != null) {
             result = context.getDataFile("");
         }
         else {
+            // TODO this method should not return null or throw an exception; we need to resolve this...
             throw new IllegalStateException("Could not retrieve valid bundle context from bundle " + bundle.getSymbolicName());
         }
+
         if (result == null) {
             throw new IllegalStateException("Could not retrieve base directory for bundle " + bundle.getSymbolicName());
         }

Added: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllBundlesCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllBundlesCommand.java?rev=1352090&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllBundlesCommand.java (added)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllBundlesCommand.java Wed Jun 20 13:27:02 2012
@@ -0,0 +1,93 @@
+/*
+ * 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.felix.deploymentadmin.spi;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.felix.deploymentadmin.AbstractDeploymentPackage;
+import org.apache.felix.deploymentadmin.BundleInfoImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.service.deploymentadmin.DeploymentException;
+import org.osgi.service.log.LogService;
+
+/**
+ * Command that uninstalls all bundles, if rolled back the bundles are restored.
+ */
+public class DropAllBundlesCommand extends Command {
+
+    public void execute(DeploymentSessionImpl session) throws DeploymentException {
+        AbstractDeploymentPackage target = session.getTargetAbstractDeploymentPackage();
+        LogService log = session.getLog();
+
+        BundleInfoImpl[] orderedTargetBundles = target.getOrderedBundleInfos();
+        for (int i = orderedTargetBundles.length - 1; i >= 0; i--) {
+            BundleInfoImpl bundleInfo = orderedTargetBundles[i];
+            // stale bundle, save a copy for rolling back and uninstall it
+            String symbolicName = bundleInfo.getSymbolicName();
+            try {
+                Bundle bundle = target.getBundle(symbolicName);
+                if (bundle != null) {
+                    bundle.uninstall();
+                    addRollback(new InstallBundleRunnable(bundle, target, log));
+                }
+            }
+            catch (BundleException be) {
+                log.log(LogService.LOG_WARNING, "Bundle '" + symbolicName + "' could not be uninstalled", be);
+            }
+        }
+    }
+
+    private static class InstallBundleRunnable implements Runnable {
+
+        private final AbstractDeploymentPackage m_target;
+        private final Bundle m_bundle;
+        private final LogService m_log;
+
+        public InstallBundleRunnable(Bundle bundle, AbstractDeploymentPackage target, LogService log) {
+            m_bundle = bundle;
+            m_target = target;
+            m_log = log;
+        }
+
+        public void run() {
+            InputStream is = null;
+            try {
+                is = m_target.getBundleStream(m_bundle.getSymbolicName());
+                if (is != null) {
+                    m_bundle.update(is);
+                }
+                throw new Exception("Unable to get Inputstream for bundle " + m_bundle.getSymbolicName());
+            }
+            catch (Exception e) {
+                m_log.log(LogService.LOG_WARNING,
+                    "Could not rollback uninstallation of bundle '" + m_bundle.getSymbolicName() + "'", e);
+            }
+            finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    }
+                    catch (IOException e) {}
+                }
+            }
+        }
+    }
+}

Added: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllResourcesCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllResourcesCommand.java?rev=1352090&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllResourcesCommand.java (added)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropAllResourcesCommand.java Wed Jun 20 13:27:02 2012
@@ -0,0 +1,112 @@
+/*
+ * 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.felix.deploymentadmin.spi;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.felix.deploymentadmin.AbstractDeploymentPackage;
+import org.apache.felix.deploymentadmin.ResourceInfoImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.deploymentadmin.DeploymentException;
+import org.osgi.service.deploymentadmin.spi.ResourceProcessor;
+import org.osgi.service.deploymentadmin.spi.ResourceProcessorException;
+import org.osgi.service.log.LogService;
+
+/**
+ * Command that drops resources.
+ */
+public class DropAllResourcesCommand extends Command {
+
+    private final CommitResourceCommand m_commitCommand;
+
+    /**
+     * Creates an instance of this command. The commit command is used to make sure
+     * the resource processors used to drop all resources will be committed at a later stage in the process.
+     *
+     * @param commitCommand The commit command that will be executed at a later stage in the process.
+     */
+    public DropAllResourcesCommand(CommitResourceCommand commitCommand) {
+        m_commitCommand = commitCommand;
+    }
+
+    public void execute(DeploymentSessionImpl session) throws DeploymentException {
+        // Allow proper rollback in case the drop fails...
+        addRollback(new RollbackCommitAction(session));
+        
+        AbstractDeploymentPackage target = session.getTargetAbstractDeploymentPackage();
+        BundleContext context = session.getBundleContext();
+        LogService log = session.getLog();
+
+        // Collect all unique paths of all processed resources...
+        Set resourceProcessors = new HashSet();
+
+        ResourceInfoImpl[] orderedTargetResources = target.getOrderedResourceInfos();
+        for (int i = orderedTargetResources.length - 1; i >= 0; i--) {
+            ResourceInfoImpl resourceInfo = orderedTargetResources[i];
+            
+            String rpName = resourceInfo.getResourceProcessor();
+            String path = resourceInfo.getPath();
+
+            if (resourceProcessors.contains(rpName)) {
+                // Already seen this RP; continue on the next one...
+                continue;
+            }
+
+            // Keep track of which resource processors we've seen already...
+            resourceProcessors.add(rpName);
+
+            ServiceReference ref = target.getResourceProcessor(path);
+            if (ref == null) {
+                log.log(LogService.LOG_ERROR, "Failed to find resource processor for '" + rpName + "'!");
+                throw new DeploymentException(DeploymentException.CODE_PROCESSOR_NOT_FOUND, "Failed to find resource processor '" + rpName + "'!");
+            }
+            
+            ResourceProcessor resourceProcessor = (ResourceProcessor) context.getService(ref);
+            if (resourceProcessor == null) {
+                log.log(LogService.LOG_ERROR, "Failed to find resource processor for '" + rpName + "'!");
+                throw new DeploymentException(DeploymentException.CODE_PROCESSOR_NOT_FOUND, "Failed to find resource processor '" + rpName + "'!");
+            }
+            
+            try {
+                if (m_commitCommand.addResourceProcessor(resourceProcessor)) {
+                    resourceProcessor.begin(session);
+                }
+                resourceProcessor.dropAllResources();
+            }
+            catch (ResourceProcessorException e) {
+                log.log(LogService.LOG_ERROR, "Failed to drop all resources for resource processor '" + rpName + "'!", e);
+                throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Failed to drop all resources for resource processor '" + rpName + "'!", e);
+            }
+        }
+    }
+    
+    private class RollbackCommitAction implements Runnable {
+        private final DeploymentSessionImpl m_session; 
+        
+        public RollbackCommitAction(DeploymentSessionImpl session) {
+            m_session = session;
+        }
+        
+        public void run() {
+            m_commitCommand.rollback(m_session);
+        }
+    }
+}

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ProcessResourceCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ProcessResourceCommand.java?rev=1352090&r1=1352089&r2=1352090&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ProcessResourceCommand.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ProcessResourceCommand.java Wed Jun 20 13:27:02 2012
@@ -65,7 +65,7 @@ public class ProcessResourceCommand exte
         AbstractInfo[] resourceInfos = (AbstractInfo[]) source.getResourceInfos();
         for (int i = 0; i < resourceInfos.length; i++) {
             AbstractInfo resourceInfo = resourceInfos[i];
-            if(!resourceInfo.isMissing()) {
+            if (!resourceInfo.isMissing()) {
                 expectedResources.put(resourceInfo.getPath(), resourceInfo);
             }
         }
@@ -100,7 +100,7 @@ public class ProcessResourceCommand exte
                             }
                             catch (ResourceProcessorException rpe) {
                                 if (rpe.getCode() == ResourceProcessorException.CODE_RESOURCE_SHARING_VIOLATION) {
-                                    throw new DeploymentException(DeploymentException.CODE_RESOURCE_SHARING_VIOLATION, "Violation while processing resource '" + name + "'", rpe);
+                                    throw new DeploymentException(DeploymentException.CODE_RESOURCE_SHARING_VIOLATION, "Sharing violation while processing resource '" + name + "'", rpe);
                                 }
                                 else {
                                     throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Error while processing resource '" + name + "'", rpe);

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java?rev=1352090&r1=1352089&r2=1352090&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java Wed Jun 20 13:27:02 2012
@@ -91,8 +91,11 @@ public class UpdateCommand extends Comma
                     }
                     throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Could not install new bundle '" + name + "'", be);
                 }
-                if (!bundle.getSymbolicName().equals(bundleInfo.getSymbolicName()) || !Version.parseVersion((String) bundle.getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION)).equals(bundleInfo.getVersion())) {
-                    throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Installed/updated bundle version and/or symbolicnames do not match what was installed/updated");
+                if (!bundle.getSymbolicName().equals(bundleInfo.getSymbolicName())) {
+                    throw new DeploymentException(DeploymentException.CODE_BUNDLE_NAME_ERROR, "Installed/updated bundle symbolicname do not match what was installed/updated");
+                }
+                if (!Version.parseVersion((String) bundle.getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION)).equals(bundleInfo.getVersion())) {
+                    throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Installed/updated bundle version do not match what was installed/updated");
                 }
             }
         }

Added: felix/trunk/deploymentadmin/itest/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/itest/pom.xml?rev=1352090&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/itest/pom.xml (added)
+++ felix/trunk/deploymentadmin/itest/pom.xml Wed Jun 20 13:27:02 2012
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+	license agreements. See the NOTICE file distributed with this work for additional 
+	information regarding copyright ownership. The ASF licenses this file to 
+	you under the Apache License, Version 2.0 (the "License"); you may not use 
+	this file except in compliance with the License. You may obtain a copy of 
+	the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
+	by applicable law or agreed to in writing, software distributed under the 
+	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
+	OF ANY KIND, either express or implied. See the License for the specific 
+	language governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.felix</groupId>
+		<artifactId>felix-parent</artifactId>
+		<version>1.2.0</version>
+		<relativePath>../../pom/pom.xml</relativePath>
+	</parent>
+	<properties>
+		<osgi.version>4.2.0</osgi.version>
+		<pax.exam.version>2.4.0</pax.exam.version>
+		<pax.exam.plugin.version>1.2.4</pax.exam.plugin.version>
+		<pax.url.aether.version>1.4.0</pax.url.aether.version>
+		<pax.swissbox.version>1.3.1</pax.swissbox.version>
+		<pax.runner.version>1.7.6</pax.runner.version>
+	</properties>
+	<name>Apache Felix DeploymentAdmin Integration Tests</name>
+	<version>0.1.1-SNAPSHOT</version>
+	<artifactId>org.apache.felix.deploymentadmin.itest</artifactId>
+	<packaging>jar</packaging>
+	<dependencies>
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>org.osgi.core</artifactId>
+			<version>${osgi.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>org.osgi.compendium</artifactId>
+			<version>${osgi.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.apache.felix.deploymentadmin</artifactId>
+			<version>0.9.1-SNAPSHOT</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.apache.felix.metatype</artifactId>
+			<version>1.0.5-SNAPSHOT</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.apache.felix.configadmin</artifactId>
+			<version>1.2.8</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.apache.felix.eventadmin</artifactId>
+			<version>1.2.14</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.10</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.ops4j.pax.exam</groupId>
+			<artifactId>pax-exam-junit4</artifactId>
+			<version>${pax.exam.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.ops4j.pax.exam</groupId>
+			<artifactId>pax-exam-container-forked</artifactId>
+			<version>${pax.exam.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.ops4j.pax.runner</groupId>
+			<artifactId>pax-runner-no-jcl</artifactId>
+			<version>${pax.runner.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.ops4j.pax.exam</groupId>
+			<artifactId>pax-exam-link-assembly</artifactId>
+			<version>${pax.exam.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.ops4j.pax.exam</groupId>
+			<artifactId>pax-exam-link-mvn</artifactId>
+			<version>${pax.exam.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.ops4j.pax.url</groupId>
+			<artifactId>pax-url-aether</artifactId>
+			<version>${pax.url.aether.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.ops4j.pax.url</groupId>
+			<artifactId>pax-url-wrap</artifactId>
+			<version>${pax.url.aether.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>javax.inject</groupId>
+			<artifactId>javax.inject</artifactId>
+			<version>1</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.apache.felix.framework</artifactId>
+			<version>4.0.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-simple</artifactId>
+			<version>1.6.0</version>
+			<scope>compile</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>org.osgi.core</artifactId>
+			<version>${osgi.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>org.osgi.compendium</artifactId>
+			<version>${osgi.version}</version>
+		</dependency>
+
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<target>1.6</target>
+					<source>1.6</source>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+</project>

Added: felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/BaseIntegrationTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/BaseIntegrationTest.java?rev=1352090&view=auto
==============================================================================
--- felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/BaseIntegrationTest.java (added)
+++ felix/trunk/deploymentadmin/itest/src/test/java/org/apache/felix/deploymentadmin/itest/BaseIntegrationTest.java Wed Jun 20 13:27:02 2012
@@ -0,0 +1,279 @@
+/*
+ * 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.felix.deploymentadmin.itest;
+
+import static org.ops4j.pax.exam.Constants.START_LEVEL_SYSTEM_BUNDLES;
+import static org.ops4j.pax.exam.Constants.START_LEVEL_TEST_BUNDLE;
+import static org.ops4j.pax.exam.CoreOptions.bootDelegationPackage;
+import static org.ops4j.pax.exam.CoreOptions.cleanCaches;
+import static org.ops4j.pax.exam.CoreOptions.felix;
+import static org.ops4j.pax.exam.CoreOptions.frameworkStartLevel;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.url;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.inject.Inject;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.deploymentadmin.itest.util.DeploymentPackageBuilder;
+import org.junit.Before;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.Version;
+import org.osgi.service.deploymentadmin.DeploymentAdmin;
+import org.osgi.service.deploymentadmin.DeploymentException;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * Provides a common base class for all deployment admin related integration tests.
+ */
+public abstract class BaseIntegrationTest extends TestCase {
+
+    protected static final int DEFAULT_TIMEOUT = 10000;
+
+    protected static final String TEST_SERVICE_NAME = "org.apache.felix.deploymentadmin.test.bundle1.TestService";
+    protected static final String TEST_FAILING_BUNDLE_RP1 = "org.apache.felix.deploymentadmin.test.rp1";
+
+    @Inject
+    protected volatile BundleContext m_context;
+    @Inject
+    protected volatile DeploymentAdmin m_deploymentAdmin;
+    @Inject
+    protected volatile PackageAdmin m_packageAdmin;
+
+    protected volatile AtomicInteger m_gate = new AtomicInteger(0);
+    protected volatile String m_testBundleBasePath;
+    protected volatile Map<String, List<Version>> m_initialBundles;
+    
+    private int cnt = 0;        
+    
+    @Configuration
+    public Option[] config() {
+        return options(
+            bootDelegationPackage("sun.*"),
+            cleanCaches(),
+            CoreOptions.systemProperty("logback.configurationFile").value("file:src/test/resources/logback.xml"),
+//            CoreOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8787"),
+
+            mavenBundle("org.slf4j", "slf4j-api").version("1.6.5").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            mavenBundle("ch.qos.logback", "logback-core").version("1.0.6").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            mavenBundle("ch.qos.logback", "logback-classic").version("1.0.6").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+
+            url("link:classpath:META-INF/links/org.ops4j.pax.exam.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            url("link:classpath:META-INF/links/org.ops4j.pax.exam.inject.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            url("link:classpath:META-INF/links/org.ops4j.pax.extender.service.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            url("link:classpath:META-INF/links/org.ops4j.base.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.core.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.extender.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.lifecycle.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            url("link:classpath:META-INF/links/org.ops4j.pax.swissbox.framework.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            url("link:classpath:META-INF/links/org.apache.geronimo.specs.atinject.link").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+
+            mavenBundle("org.osgi", "org.osgi.core").version("4.2.0").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            mavenBundle("org.osgi", "org.osgi.compendium").version("4.2.0").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").version("3.0.0").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            mavenBundle("org.apache.felix", "org.apache.felix.deploymentadmin").version("0.9.1-SNAPSHOT").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            mavenBundle("org.apache.felix", "org.apache.felix.eventadmin").version("1.2.14").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            mavenBundle("org.apache.felix", "org.apache.felix.configadmin").version("1.2.8").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            mavenBundle("org.apache.felix", "org.apache.felix.log").version("1.0.1").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+//            mavenBundle("org.apache.felix", "org.apache.felix.shell").version("1.4.3").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+//            mavenBundle("org.apache.felix", "org.apache.felix.shell.tui").version("1.4.1").startLevel(START_LEVEL_SYSTEM_BUNDLES),
+            
+            junitBundles(),
+            frameworkStartLevel(START_LEVEL_TEST_BUNDLE),
+            felix());
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        assertNotNull("No bundle context?!", m_context);
+
+        File f = new File("../testbundles").getAbsoluteFile();
+        assertTrue("Failed to find test bundles directory?!", f.exists() && f.isDirectory());
+
+        m_testBundleBasePath = f.getAbsolutePath();
+
+        m_context.addFrameworkListener(new FrameworkListener() {
+            public void frameworkEvent(FrameworkEvent event) {
+                if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
+                    m_gate.getAndIncrement();
+                }
+            }
+        });
+        
+        m_initialBundles = new HashMap<String, List<Version>>();
+        
+        for (Bundle bundle : m_context.getBundles()) {
+            List<Version> versions = m_initialBundles.get(bundle.getSymbolicName());
+            if (versions == null) {
+                versions = new ArrayList<Version>();
+                m_initialBundles.put(bundle.getSymbolicName(), versions);
+            }
+            versions.add(bundle.getVersion());
+        }
+    }
+
+    protected void assertBundleExists(String symbolicName, String version) {
+        boolean result = isBundleAdded(symbolicName, version);
+        if (!result) {
+            fail("Bundle " + symbolicName + ", v" + version + " does not exist?!\nCurrent additional bundles are: " + getCurrentBundles());
+        }
+    }
+
+    protected void assertBundleNotExists(String symbolicName, String version) {
+        boolean result = isBundleAdded(symbolicName, version);
+        if (result) {
+            fail("Bundle " + symbolicName + ", v" + version + " does (still) exist?!\nCurrent additional bundles are: " + getCurrentBundles());
+        }
+    }
+
+    protected void assertDeploymentException(int expectedCode, DeploymentException exception) {
+        assertEquals("Invalid exception code?!\nException = " + exception, expectedCode, exception.getCode());
+    }
+
+    protected void awaitRefreshPackagesEvent() throws Exception {
+        long start = System.currentTimeMillis();
+        while ((m_gate.get() == 0) && ((System.currentTimeMillis() - start) < DEFAULT_TIMEOUT)) {
+            TimeUnit.MILLISECONDS.sleep(100);
+        }
+        assertTrue("Failed to obtain refresh packages event?! " + m_gate.get(), m_gate.get() > 0);
+        m_gate.set(0);
+    }
+
+    protected <T> T awaitService(String serviceName) throws Exception {
+        ServiceTracker tracker = new ServiceTracker(m_context, serviceName, null);
+        tracker.open();
+        T result;
+        try {
+            result = (T) tracker.waitForService(DEFAULT_TIMEOUT);
+        }
+        finally {
+            tracker.close();
+        }
+        return result;
+    }
+
+    protected DeploymentPackageBuilder createNewDeploymentPackageBuilder(String version) {
+        return createDeploymentPackageBuilder(String.format("itest%d", ++cnt), version);
+    }
+    
+    protected DeploymentPackageBuilder createDeploymentPackageBuilder(String symName, String version) {
+        return DeploymentPackageBuilder.create(symName, version);
+    }
+    
+    protected Map<String, List<Version>> getCurrentBundles() {
+        Map<String, List<Version>> bundles = new HashMap<String, List<Version>>();
+        for (Bundle bundle : m_context.getBundles()) {
+            String symbolicName = bundle.getSymbolicName();
+            Version version = bundle.getVersion();
+            
+            // Is is not part of any of the initially provisioned bundles?
+            List<Version> versions = m_initialBundles.get(symbolicName);
+            if ((versions == null) || !versions.contains(version)) {
+                List<Version> versions2 = bundles.get(symbolicName);
+                if (versions2 == null) {
+                    versions2 = new ArrayList<Version>();
+                    bundles.put(symbolicName, versions2);
+                }
+                versions2.add(version);
+            }
+        }
+        return bundles;
+    }
+    
+    protected String getSymbolicName(String baseName) {
+        return "testbundles.".concat(baseName);
+    }
+
+    protected URL getTestResource(String resourceName) {
+        if (!resourceName.startsWith("/")) {
+            resourceName = "/".concat(resourceName);
+        }
+        URL resource = getClass().getResource(resourceName);
+        assertNotNull("No such resource: " + resourceName, resource);
+        return resource;
+    }
+
+    /**
+     * @param baseName
+     * @return
+     * @throws MalformedURLException
+     */
+    protected URL getTestBundle(String baseName) throws MalformedURLException {
+        File f = new File(m_testBundleBasePath, String.format("%1$s/target/org.apache.felix.deploymentadmin.test.%1$s-1.0.0.jar", baseName));
+        assertTrue("No such bundle: " + f, f.exists() && f.isFile());
+        return f.toURI().toURL();
+    }
+    
+    protected boolean isBundleActive(Bundle bundle) {
+        return isBundleInState(bundle, Bundle.ACTIVE);
+    }
+
+    protected boolean isBundleAdded(String symbolicName, String version) {
+        return isBundleAdded(symbolicName, new Version(version));
+    }
+
+    protected boolean isBundleAdded(String symbolicName, Version version) {
+        Map<String, List<Version>> bundles = getCurrentBundles();
+
+        List<Version> availableVersions = bundles.get(symbolicName);
+        return (availableVersions != null) && availableVersions.contains(version);
+    }
+
+    protected boolean isBundleInstalled(Bundle bundle) {
+        return isBundleInState(bundle, Bundle.INSTALLED);
+    }
+
+    protected boolean isBundleInState(Bundle bundle, int state) {
+        return ((bundle.getState() & state) != 0);
+    }
+
+    protected boolean isBundleRemoved(String symbolicName, String version) {
+        return isBundleRemoved(symbolicName, new Version(version));
+    }
+    
+    protected boolean isBundleRemoved(String symbolicName, Version version) {
+        Map<String, List<Version>> bundles = getCurrentBundles();
+
+        List<Version> availableVersions = bundles.get(symbolicName);
+        return (availableVersions == null) || !availableVersions.contains(version);
+    }
+
+    protected boolean isBundleResolved(Bundle bundle) {
+        return isBundleInState(bundle, Bundle.RESOLVED);
+    }
+}



Mime
View raw message