MetaType:
- Changed the name attribute of an AD element from required to optional in metatype reader (as specced by compendium 105.8)

DeploymentAdmin:
- Use correct dir for persistence
- Iterating backwards was missing correct initialisation index in several locations
- Resource processors only used for dropping resources are correctly committed now
- Fixed bug where the processed resources could be read from the incoming deploymentpackage stream while processing bundles
- Stale customizer bundles are not uninstalled immediately

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@634590 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java
index be871e4..7fa6076 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/AbstractDeploymentPackage.java
@@ -177,9 +177,13 @@
             if (processor != null) {
                 try {
                     ServiceReference[] services = m_bundleContext.getServiceReferences(ResourceProcessor.class.getName(), "(" + org.osgi.framework.Constants.SERVICE_PID + "=" + processor + ")");
-                    if (services.length > 0) {
+                    if (services != null && services.length > 0) {
                         return services[0];
                     }
+                    else {
+                    	return null;
+                    }
+                    
                 }
                 catch (InvalidSyntaxException e) {
                 	// TODO: log this
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java
index ace0dbb..aec851c 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java
@@ -102,7 +102,7 @@
                 if (packages[i].isDirectory()) {
                     try {
                         File index = new File(packages[i], PACKAGEINDEX_FILE);
-                        File contents = new File(packages[i], PACKAGE_DIR);
+                        File contents = new File(packages[i], PACKAGECONTENTS_DIR);
                         FileDeploymentPackage dp = new FileDeploymentPackage(index, contents, m_context);
                         m_packages.put(dp.getName(), dp);
                     }
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentPackageManifest.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentPackageManifest.java
index 9a3531a..f450b94 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentPackageManifest.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentPackageManifest.java
@@ -56,7 +56,7 @@
 
         Attributes mainAttributes = m_manifest.getMainAttributes();
 
-        // TODO: verify symbolic name for valid format/chars
+        // TODO: verify symbolic name and entry-names for valid format/chars
         m_symbolicName = getNonNullHeader(mainAttributes.getValue(Constants.DEPLOYMENTPACKAGE_SYMBOLICMAME));
 
         String version = getNonNullHeader(mainAttributes.getValue(Constants.DEPLOYMENTPACKAGE_VERSION));
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/Command.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/Command.java
index cb5790e..eed76cc 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/Command.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/Command.java
@@ -50,7 +50,7 @@
      * command was never executed, a best effort should be made though.
      */
     public void rollback() {
-        for (ListIterator i = m_rollback.listIterator(); i.hasPrevious();) {
+        for (ListIterator i = m_rollback.listIterator(m_commit.size()); i.hasPrevious();) {
             Runnable runnable = (Runnable) i.previous();
             runnable.run();
         }
@@ -61,7 +61,7 @@
      * Commits all changes the command may have defined when it was executed by calling the <code>execute()</code> method.
      */
     protected void commit() {
-        for (ListIterator i = m_commit.listIterator(); i.hasPrevious();) {
+        for (ListIterator i = m_commit.listIterator(m_commit.size()); i.hasPrevious();) {
             Runnable runnable = (Runnable) i.previous();
             runnable.run();
         }
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/CommitResourceCommand.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/CommitResourceCommand.java
index 1262706..a70fed4 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/CommitResourceCommand.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/CommitResourceCommand.java
@@ -36,8 +36,8 @@
     private final List m_processors = new ArrayList();
 
     public void execute(DeploymentSessionImpl session) throws DeploymentException {
-        for (ListIterator i = m_processors.listIterator(); i.hasPrevious();) {
-            ResourceProcessor processor = (ResourceProcessor) i.previous();
+        for (ListIterator i = m_processors.listIterator(m_processors.size()); i.hasPrevious();) {
+    		ResourceProcessor processor = (ResourceProcessor) i.previous();
             try {
                 processor.prepare();
             }
@@ -46,7 +46,7 @@
                 throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Preparing commit for resource processor failed", e);
             }
         }
-        for (ListIterator i = m_processors.listIterator(); i.hasPrevious();) {
+        for (ListIterator i = m_processors.listIterator(m_processors.size()); i.hasPrevious();) {
             ResourceProcessor processor = (ResourceProcessor) i.previous();
             try {
                 processor.commit();
@@ -56,10 +56,11 @@
                 // TODO Throw exception?
             }
         }
+        m_processors.clear();
     }
 
     public void rollback() {
-        for (ListIterator i = m_processors.listIterator(); i.hasPrevious();) {
+        for (ListIterator i = m_processors.listIterator(m_processors.size()); i.hasPrevious();) {
             ResourceProcessor processor = (ResourceProcessor) i.previous();
             try {
                 processor.rollback();
@@ -75,15 +76,17 @@
      * Add a resource processor, all resource processors that are added will be committed when the command is executed.
      *
      * @param processor The resource processor to add.
+     * @return true if the resource processor was added, false if it was already added.
      */
-    public void addResourceProcessor(ResourceProcessor processor) {
+    public boolean addResourceProcessor(ResourceProcessor processor) {
         for (Iterator i = m_processors.iterator(); i.hasNext();) {
             ResourceProcessor proc = (ResourceProcessor) i.next();
             if (proc == processor) {
-                return;
+                return false;
             }
         }
         m_processors.add(processor);
+        return true;
     }
 
     public void run() {
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DeploymentSessionImpl.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DeploymentSessionImpl.java
index 6cf05da..849d651 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DeploymentSessionImpl.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DeploymentSessionImpl.java
@@ -82,7 +82,7 @@
     }
 
     private void rollback(List executedCommands) {
-        for (ListIterator i = executedCommands.listIterator(); i.hasPrevious();) {
+        for (ListIterator i = executedCommands.listIterator(executedCommands.size()); i.hasPrevious();) {
             Command command = (Command) i.previous();
             command.rollback();
         }
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropBundleCommand.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropBundleCommand.java
index b894702..61133bf 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropBundleCommand.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropBundleCommand.java
@@ -41,7 +41,7 @@
         BundleInfoImpl[] orderedTargetBundles = target.getOrderedBundleInfos();
         for (int i = orderedTargetBundles.length - 1; i >= 0; i--) {
             BundleInfoImpl bundleInfo = orderedTargetBundles[i];
-            if (source.getBundleInfoByPath(bundleInfo.getPath()) == null) {
+            if (!bundleInfo.isCustomizer() && source.getBundleInfoByPath(bundleInfo.getPath()) == null) {
                 // stale bundle, save a copy for rolling back and uninstall it
                 String symbolicName = bundleInfo.getSymbolicName();
                 try {
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropResourceCommand.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropResourceCommand.java
index be32fea..fd54bf4 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropResourceCommand.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/DropResourceCommand.java
@@ -60,7 +60,9 @@
                     ResourceProcessor resourceProcessor = (ResourceProcessor) context.getService(ref);
                     if (resourceProcessor != null) {
                         try {
-                            m_commitCommand.addResourceProcessor(resourceProcessor);
+                            if (m_commitCommand.addResourceProcessor(resourceProcessor)) {
+                            	resourceProcessor.begin(session);
+                            }
                             resourceProcessor.dropped(path);
                         }
                         catch (ResourceProcessorException e) {
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ProcessResourceCommand.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ProcessResourceCommand.java
index 97f3bb9..772faa8 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ProcessResourceCommand.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/ProcessResourceCommand.java
@@ -66,30 +66,29 @@
         }
 
         try {
-            for (AbstractInfo jarEntry = source.getNextEntry(); (jarEntry != null) && (!expectedResources.isEmpty()); jarEntry = source.getNextEntry()) {
-                String name = jarEntry.getPath();
-
-                if (!expectedResources.containsKey(name)) {
-                    throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Resource '" + name + "' is not described in the manifest.");
-                }
+        	while (!expectedResources.isEmpty()) {
+            	AbstractInfo jarEntry = source.getNextEntry();
+            	if (jarEntry == null) {
+                	throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Expected more resources in the stream: " + expectedResources.keySet());
+            	}
+            	
+            	String name = jarEntry.getPath();
 
                 ResourceInfoImpl resourceInfo = (ResourceInfoImpl) expectedResources.remove(name);
-
-                String resourceProcessorPID = resourceInfo.getResourceProcessor();
-                if (resourceProcessorPID == null) {
-                    // no resource processor specified, resource can be ignored
-                    continue;
+                if (resourceInfo == null) {
+                	throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Resource '" + name + "' is not described in the manifest.");
                 }
 
-                ServiceReference ref = source.getResourceProcessor(resourceProcessorPID);
+                ServiceReference ref = source.getResourceProcessor(name);
                 if (ref != null) {
                     String serviceOwnerSymName = ref.getBundle().getSymbolicName();
                     if (source.getBundleInfoByName(serviceOwnerSymName) != null) {
                         ResourceProcessor resourceProcessor = (ResourceProcessor) context.getService(ref);
                         if (resourceProcessor != null) {
-                            resourceProcessor.begin(session);
                             try {
-                                m_commitCommand.addResourceProcessor(resourceProcessor);
+                                if (m_commitCommand.addResourceProcessor(resourceProcessor)) {
+                                	resourceProcessor.begin(session);
+                                }
                                 resourceProcessor.process(name, source.getCurrentEntryStream());
                             }
                             catch (ResourceProcessorException rpe) {
diff --git a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java
index 95b7d69..1d611ca 100644
--- a/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java
+++ b/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/spi/UpdateCommand.java
@@ -55,13 +55,18 @@
         }
 
         try {
-            for (AbstractInfo entry = source.getNextEntry(); (entry != null) && (!expectedBundles.isEmpty()); entry = source.getNextEntry()) {
-                String name = entry.getPath();
-                if (!expectedBundles.containsKey(name)) {
+            while (!expectedBundles.isEmpty()) {
+            	AbstractInfo entry = source.getNextEntry();
+            	if (entry == null) {
+                	throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Expected more bundles in the stream: " + expectedBundles.keySet());
+            	}
+            	
+            	String name = entry.getPath();
+                BundleInfoImpl bundleInfo = (BundleInfoImpl) expectedBundles.remove(name);
+                if (bundleInfo == null) {
                     throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Resource '" + name + "' is not described in the manifest.");
                 }
 
-                BundleInfoImpl bundleInfo = (BundleInfoImpl) expectedBundles.remove(name);
                 Bundle bundle = source.getBundle(bundleInfo.getSymbolicName());
                 try {
                     if (bundle == null) {
diff --git a/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java b/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java
index d73318e..65ed8bc 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java
@@ -281,7 +281,7 @@
     {
         AD ad = this.createAD();
         ad.setID( this.getRequiredAttribute( "id" ) );
-        ad.setName( this.getRequiredAttribute( "name" ) );
+        ad.setName( this.getOptionalAttribute( "name" ) );
         ad.setDescription( this.getOptionalAttribute( "description" ) );
         ad.setType( this.getRequiredAttribute( "type" ) );
         ad.setCardinality( this.getOptionalAttribute( "cardinality", 0 ) );