You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ma...@apache.org on 2012/05/18 01:41:59 UTC

svn commit: r1339925 - in /felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin: DeploymentAdminImpl.java ExplodingOutputtingInputStream.java FileDeploymentPackage.java

Author: marrs
Date: Thu May 17 23:41:58 2012
New Revision: 1339925

URL: http://svn.apache.org/viewvc?rev=1339925&view=rev
Log:
Various fixes, the most important one was properly closing a stream that was reading a manifest in FileDeploymentPackage, to improve robustness when something goes wrong while manipulating files. The old code worked everywhere but on Windows, where a locked file prevented deletion, causing problems updating deployment packages. If you use Windows, you definitely need this fix.

Modified:
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/DeploymentAdminImpl.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/ExplodingOutputtingInputStream.java
    felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/FileDeploymentPackage.java

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=1339925&r1=1339924&r2=1339925&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 Thu May 17 23:41:58 2012
@@ -64,10 +64,10 @@ public class DeploymentAdminImpl impleme
 
     private static final long TIMEOUT = 10000;
 
-    private BundleContext m_context; /* will be injected by dependencymanager */
-    private PackageAdmin m_packageAdmin;    /* will be injected by dependencymanager */
-    private EventAdmin m_eventAdmin; /* will be injected by dependencymanager */
-    private LogService m_log;        /* will be injected by dependencymanager */
+    private volatile BundleContext m_context;       /* will be injected by dependencymanager */
+    private volatile PackageAdmin m_packageAdmin;   /* will be injected by dependencymanager */
+    private volatile EventAdmin m_eventAdmin;       /* will be injected by dependencymanager */
+    private volatile LogService m_log;              /* will be injected by dependencymanager */
     private DeploymentSessionImpl m_session = null;
     private final Map m_packages = new HashMap();
     private final List m_commandChain = new ArrayList();
@@ -116,7 +116,6 @@ public class DeploymentAdminImpl impleme
         }
     }
 
-
     public void stop() {
     	cancel();
     }
@@ -213,11 +212,14 @@ public class DeploymentAdminImpl impleme
                 throw de;
             }
             try {
-                jarInput.close();
+                // note that calling close on this stream will wait until asynchronous processing
+                // is done
+                input.close();
             }
             catch (IOException e) {
-                // nothing we can do
-                m_log.log(LogService.LOG_WARNING, "Could not close stream properly", e);
+                succeeded = false;
+                m_log.log(LogService.LOG_ERROR, "Could not close stream properly", e);
+                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);
@@ -231,10 +233,13 @@ public class DeploymentAdminImpl impleme
                     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 {
+            }
+            else {
                 File targetPackage = m_context.getDataFile(PACKAGE_DIR + File.separator + source.getName());
                 targetPackage.mkdirs();
-                ExplodingOutputtingInputStream.replace(targetPackage, tempPackage);
+                if (!ExplodingOutputtingInputStream.replace(targetPackage, tempPackage)) {
+                	throw new DeploymentException(DeploymentException.CODE_OTHER_ERROR, "Could not replace " + targetPackage + " with " + tempPackage);
+                }
             }
             FileDeploymentPackage fileDeploymentPackage = null;
             try {

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/ExplodingOutputtingInputStream.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/ExplodingOutputtingInputStream.java?rev=1339925&r1=1339924&r2=1339925&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/ExplodingOutputtingInputStream.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/ExplodingOutputtingInputStream.java Thu May 17 23:41:58 2012
@@ -51,6 +51,7 @@ class ExplodingOutputtingInputStream ext
     private final File m_contentDir;
     private final File m_indexFile;
     private final PipedInputStream m_input;
+    private Exception m_exception;
 
     /**
      * Creates an instance of this class.
@@ -65,8 +66,15 @@ class ExplodingOutputtingInputStream ext
     }
 
     public void close() throws IOException {
-        super.close();
-        waitFor();
+        try {
+            super.close();
+            if (m_exception != null) {
+                throw new IOException("Exception while processing the stream in the background: " + m_exception.getMessage(), m_exception);
+            }
+        }
+        finally {
+            waitFor();
+        }
     }
 
     private ExplodingOutputtingInputStream(InputStream inputStream, PipedOutputStream output, File index, File root) throws IOException {
@@ -121,12 +129,20 @@ class ExplodingOutputtingInputStream ext
             }
         }
         catch (IOException ex) {
-            // TODO: review the impact of this happening and how to react
+            pushException(ex);
         }
         finally {
             if (writer != null) {
                 writer.close();
             }
+            if (input != null) {
+                try {
+                    input.close();
+                }
+                catch (IOException e) {
+                    pushException(e);
+                }
+            }
         }
         
         try {
@@ -137,15 +153,21 @@ class ExplodingOutputtingInputStream ext
             }
         }
         catch (IOException e) {
-            e.printStackTrace();
+            pushException(e);
         }
     }
+    
+    private void pushException(Exception e) {
+        Exception e2 = new Exception(e.getMessage());
+        e2.setStackTrace(e.getStackTrace());
+        if (m_exception != null) {
+            e2.initCause(m_exception);
+        }
+        m_exception = e2;
+    }
 
     public static boolean replace(File target, File source) {
-        if (delete(target, true)) {
-            return rename(source, target);
-        }
-        return false;
+        return delete(target, true) && rename(source, target);
     }
     
     public static boolean copy(File from, File to) {
@@ -217,13 +239,20 @@ class ExplodingOutputtingInputStream ext
     private static boolean delete(File root, boolean deleteRoot) {
         boolean result = true;
         if (root.isDirectory()) {
-            File[] childs = root.listFiles();
-            for (int i = 0; i < childs.length; i++) {
-                result &= delete(childs[i], true);
+            File[] files = root.listFiles();
+            for (int i = 0; i < files.length; i++) {
+            	if (files[i].isDirectory()) {
+            		result &= delete(files[i], true);
+            	}
+            	else {
+            		result &= files[i].delete();
+            	}
             }
         }
         if (deleteRoot) {
-            result &= root.delete();
+        	if (root.exists()) {
+        		result &= root.delete();
+        	}
         }
         return result;
     }
@@ -274,7 +303,10 @@ class ExplodingOutputtingInputStream ext
 
         for (Iterator iter = targetFiles.iterator(); iter.hasNext();) {
             String path = (String) iter.next();
-            (new File(target, path)).delete();
+            File targetFile = new File(target, path);
+            if (!targetFile.delete()) {
+                throw new IOException("Could not delete " + targetFile);
+            }
         }
 
         GZIPOutputStream outputStream = new GZIPOutputStream(new FileOutputStream(new File(target, "META-INF/MANIFEST.MF")));
@@ -295,12 +327,7 @@ class ExplodingOutputtingInputStream ext
         }
         finally {
             if (reader != null) {
-                try {
-                    reader.close();
-                }
-                catch (IOException e) {
-                    // Not much we can do
-                }
+                reader.close();
             }
         }
     }

Modified: felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/FileDeploymentPackage.java
URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/FileDeploymentPackage.java?rev=1339925&r1=1339924&r2=1339925&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/FileDeploymentPackage.java (original)
+++ felix/trunk/deploymentadmin/deploymentadmin/src/main/java/org/apache/felix/deploymentadmin/FileDeploymentPackage.java Thu May 17 23:41:58 2012
@@ -20,6 +20,7 @@ package org.apache.felix.deploymentadmin
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -52,11 +53,27 @@ public class FileDeploymentPackage exten
     }
 
     private FileDeploymentPackage(List index, File packageDir, BundleContext bundleContext, DeploymentAdminImpl deploymentAdmin) throws DeploymentException, IOException {
-        super(new Manifest(new GZIPInputStream(new FileInputStream(new File(packageDir, (String) index.remove(0))))), bundleContext, deploymentAdmin);
+        super(readManifest(index, packageDir), bundleContext, deploymentAdmin);
         m_index = index;
         m_contentsDir = packageDir;
     }
 
+    private static Manifest readManifest(List index, File packageDir) throws FileNotFoundException, IOException {
+        final File manifestFile = new File(packageDir, (String) index.remove(0));
+        InputStream is = null;
+        Manifest mf = null;
+        try {
+            is = new GZIPInputStream(new FileInputStream(manifestFile));
+            mf = new Manifest(is);
+        }
+        finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+        return mf;
+    }
+
     public BundleInfoImpl[] getOrderedBundleInfos() {
         List result = new ArrayList();
         for(Iterator i = m_index.iterator(); i.hasNext();) {