[FELIX-3047] Infinite loop in File Install if java.io.tmpdir is non-writable

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1301383 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java b/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java
index e50ce59..0b55e48 100644
--- a/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java
+++ b/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java
@@ -97,7 +97,7 @@
 
     static final SecureRandom random = new SecureRandom();
 
-    static final File javaIoTmpdir = new File(System.getProperty("java.io.tmpdir"));
+    final File javaIoTmpdir = new File(System.getProperty("java.io.tmpdir"));
 
     Dictionary properties;
     File watchedDirectory;
@@ -560,6 +560,9 @@
     {
         if (tmpDir == null)
         {
+            if (!javaIoTmpdir.exists() && !javaIoTmpdir.mkdirs()) {
+                throw new IllegalStateException("Unable to create temporary directory " + javaIoTmpdir);
+            }
             for (;;)
             {
                 File f = new File(javaIoTmpdir, "fileinstall-" + Long.toString(random.nextLong()));
diff --git a/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java b/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java
index 22fc8f9..63fe969 100644
--- a/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java
+++ b/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java
@@ -168,11 +168,11 @@
 
         assertEquals( "POLL parameter correctly read", 500l, dw.poll );
         assertEquals( "LOG_LEVEL parameter correctly read", 1, dw.logLevel );
-        assertTrue( "DIR parameter correctly read", dw.watchedDirectory.getAbsolutePath().endsWith(
-            "src" + File.separatorChar + "test" + File.separatorChar + "resources" ) );
+        assertTrue("DIR parameter correctly read", dw.watchedDirectory.getAbsolutePath().endsWith(
+                "src" + File.separatorChar + "test" + File.separatorChar + "resources"));
         assertTrue( "TMPDIR parameter correctly read", dw.tmpDir.getAbsolutePath().endsWith(
             "src" + File.separatorChar + "test" + File.separatorChar + "resources" ) );
-        assertEquals( "START_NEW_BUNDLES parameter correctly read", false, dw.startBundles );
+        assertEquals("START_NEW_BUNDLES parameter correctly read", false, dw.startBundles);
         assertEquals( "FILTER parameter correctly read", ".*\\.cfg", dw.filter );
         EasyMock.verify(new Object[]{mockBundleContext});
     }
@@ -189,11 +189,11 @@
 
         assertTrue( "DIR parameter correctly read", dw.watchedDirectory.getAbsolutePath().endsWith(
             "src" + File.separatorChar + "test" + File.separatorChar + "resources" ) );
-        assertEquals( "Default POLL parameter correctly read", 2000l, dw.poll );
+        assertEquals("Default POLL parameter correctly read", 2000l, dw.poll);
         assertEquals( "Default LOG_LEVEL parameter correctly read", 1, dw.logLevel );
-        assertTrue( "Default TMPDIR parameter correctly read", dw.tmpDir.getAbsolutePath().startsWith(
-                new File(System.getProperty("java.io.tmpdir")).getAbsolutePath()) );
-        assertEquals( "Default START_NEW_BUNDLES parameter correctly read", true, dw.startBundles );
+        assertTrue("Default TMPDIR parameter correctly read", dw.tmpDir.getAbsolutePath().startsWith(
+                new File(System.getProperty("java.io.tmpdir")).getAbsolutePath()));
+        assertEquals("Default START_NEW_BUNDLES parameter correctly read", true, dw.startBundles);
         assertEquals( "Default FILTER parameter correctly read", null, dw.filter );
         EasyMock.verify(new Object[]{mockBundleContext});
     }
@@ -205,7 +205,7 @@
         EasyMock.expect(mockBundleContext.createFilter((String) EasyMock.anyObject()))
                         .andReturn(null);
         EasyMock.expect(Long.valueOf(mockPackageAdmin.getBundleType(mockBundle)))
-                        .andReturn(new Long(PackageAdmin.BUNDLE_TYPE_FRAGMENT) );
+                        .andReturn(new Long(PackageAdmin.BUNDLE_TYPE_FRAGMENT));
         EasyMock.replay(new Object[]{mockBundleContext, mockPackageAdmin, mockBundle});
 
         FileInstall.padmin = new MockServiceTracker( mockBundleContext, mockPackageAdmin );
@@ -215,6 +215,43 @@
 
         EasyMock.verify(new Object[]{mockBundleContext});
     }
+    
+    public void testInvalidTempDir() throws Exception
+    {
+        String oldTmpDir = System.getProperty("java.io.tmpdir");
+        
+        try 
+        {
+            File parent = new File("target/tmp");
+            parent.mkdirs();
+            parent.setWritable(false, false);
+            File tmp = new File(parent, "tmp");
+            System.setProperty("java.io.tmpdir", tmp.toString());
+
+            mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
+            EasyMock.expect(mockBundleContext.createFilter((String) EasyMock.anyObject()))
+                    .andReturn(null);
+            EasyMock.expect(Long.valueOf(mockPackageAdmin.getBundleType(mockBundle)))
+                    .andReturn(new Long(PackageAdmin.BUNDLE_TYPE_FRAGMENT));
+            EasyMock.replay(new Object[]{mockBundleContext, mockPackageAdmin, mockBundle});
+    
+            FileInstall.padmin = new MockServiceTracker( mockBundleContext, mockPackageAdmin );
+            
+            try 
+            {
+                dw = new DirectoryWatcher( props, mockBundleContext );
+                fail("Expected an IllegalStateException");
+            } 
+            catch (IllegalStateException e)
+            {
+                // expected
+            }
+        }
+        finally
+        {
+            System.setProperty("java.io.tmpdir", oldTmpDir);
+        }
+    }
 
 
 }