You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gn...@apache.org on 2014/03/18 18:53:28 UTC

svn commit: r1578984 - in /felix/trunk/fileinstall/src: main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java

Author: gnodet
Date: Tue Mar 18 17:53:28 2014
New Revision: 1578984

URL: http://svn.apache.org/r1578984
Log:
[FELIX-4436] DirectoryWatcher should not refresh transformed bundles on every start-up

Modified:
    felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java
    felix/trunk/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java

Modified: felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java
URL: http://svn.apache.org/viewvc/felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java?rev=1578984&r1=1578983&r2=1578984&view=diff
==============================================================================
--- felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java (original)
+++ felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java Tue Mar 18 17:53:28 2014
@@ -848,13 +848,33 @@ public class DirectoryWatcher extends Th
                     // Let's try to interpret the location as a file path
                     uri = new File(location).toURI().normalize();
                 }
-                path = uri.getPath();
+                if (uri.isOpaque() && uri.getSchemeSpecificPart() != null)
+                {
+                    // blueprint:file:/tmp/foo/baa.jar -> file:/tmp/foo/baa.jar
+                    // blueprint:mvn:foo.baa/baa/0.0.1 -> mvn:foo.baa/baa/0.0.1
+                    // wrap:file:/tmp/foo/baa-1.0.jar$Symbolic-Name=baa&Version=1.0 -> file:/tmp/foo/baa-1.0.jar$Symbolic-Name=baa&Version1.0
+                    final String schemeSpecificPart = uri.getSchemeSpecificPart();
+                    // extract content behind the 'file:' protocol of scheme specific path
+                    final int lastIndexOfFileProtocol = schemeSpecificPart.lastIndexOf("file:");
+                    final int offsetFileProtocol = lastIndexOfFileProtocol >= 0 ? lastIndexOfFileProtocol + "file:".length() : 0;
+                    final int firstIndexOfDollar = schemeSpecificPart.indexOf("$");
+                    final int endOfPath = firstIndexOfDollar >= 0 ? firstIndexOfDollar : schemeSpecificPart.length();
+                    // file:/tmp/foo/baa.jar -> /tmp/foo/baa.jar
+                    // mvn:foo.baa/baa/0.0.1 -> mvn:foo.baa/baa/0.0.1
+                    // file:/tmp/foo/baa-1.0.jar$Symbolic-Name=baa&Version=1.0 -> /tmp/foo/baa-1.0.jar
+                    path = schemeSpecificPart.substring(offsetFileProtocol, endOfPath);
+                }
+                else
+                {
+                    // file:/tmp/foo/baa.jar -> /tmp/foo/baa.jar
+                    // mnv:foo.baa/baa/0.0.1 -> foo.baa/baa/0.0.1
+                    path = uri.getPath();
+                }
             }
             if (path == null)
             {
                 // jar.getPath is null means we could not parse the location
-                // as a meaningful URI or file path. e.g., location
-                // represented an Opaque URI.
+                // as a meaningful URI or file path.
                 // We can't do any meaningful processing for this bundle.
                 continue;
             }

Modified: felix/trunk/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java?rev=1578984&r1=1578983&r2=1578984&view=diff
==============================================================================
--- felix/trunk/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java (original)
+++ felix/trunk/fileinstall/src/test/java/org/apache/felix/fileinstall/internal/DirectoryWatcherTest.java Tue Mar 18 17:53:28 2014
@@ -20,14 +20,20 @@ package org.apache.felix.fileinstall.int
 
 
 import java.io.File;
+import java.net.URISyntaxException;
 import java.util.Dictionary;
+import java.util.HashSet;
 import java.util.Hashtable;
-
+import java.util.Map;
+import java.util.Set;
 import junit.framework.TestCase;
+import org.apache.felix.fileinstall.ArtifactListener;
 import org.easymock.EasyMock;
+import org.junit.Assert;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleListener;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.log.LogService;
 import org.osgi.service.packageadmin.PackageAdmin;
 
@@ -51,7 +57,7 @@ public class DirectoryWatcherTest extend
         super.setUp();
         mockBundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
         mockPackageAdmin = (PackageAdmin) EasyMock.createMock(PackageAdmin.class);
-        mockBundle = (Bundle) EasyMock.createMock(Bundle.class);
+        mockBundle = (Bundle) EasyMock.createNiceMock(Bundle.class);
         props.put( DirectoryWatcher.DIR, new File( "target/load" ).getAbsolutePath() );
 
         // Might get called, but most of the time it doesn't matter whether they do or don't.
@@ -253,5 +259,180 @@ public class DirectoryWatcherTest extend
         }
     }
 
+    /**
+     * Test the {@link DirectoryWatcher#initializeCurrentManagedBundles()} in conjunction with a non opaque Bundle Location.
+     * Assert that a new created {@link Artifact} will be added into the {@link DirectoryWatcher#currentManagedArtifacts}.
+     * 
+     * The {@link DirectoryWatcher#process(java.util.Set)} execution will not be called.
+     * This test breaks the execution in {@link Scanner#initialize(java.util.Map)}.
+     * @throws URISyntaxException 
+     */
+    public void testInitializeCurrentManagedBundlesNonOpaqueURIOnBundleLocation() throws URISyntaxException
+    {
+        final RuntimeException expectedException = new RuntimeException("expected exception to break execution on defined point.");
+        final File watchedDirectoryFile = new File("src/test/resources/watched");
+        final String watchedDirectoryPath = watchedDirectoryFile.getAbsolutePath();
+
+        final String bundleFileName = "firstjar.jar";
+        final File bundleFile = new File(watchedDirectoryPath,bundleFileName);
+        final String bundleLocation = "file:"+watchedDirectoryPath+'/'+bundleFileName;
+
+        // break execution
+        final Scanner scanner = new Scanner(watchedDirectoryFile)
+        {
+            public void initialize(Map checksums)
+            {
+                throw expectedException;
+            }
+        };
+
+        mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
+        EasyMock.expect(mockBundleContext.getBundles()).andReturn(new Bundle[]{mockBundle});
+        EasyMock.expect(mockBundleContext.getDataFile((String) EasyMock.anyObject())).andReturn(null).anyTimes();
+        EasyMock.expect(mockBundle.getLocation()).andReturn(bundleLocation).anyTimes();
+        final Map mockCurrentManagedArtifacts = (Map)EasyMock.createNiceMock(Map.class);
+        EasyMock.expect(mockCurrentManagedArtifacts.put(EasyMock.eq(bundleFile), (Artifact)EasyMock.anyObject())).andReturn(null).times(1);
+
+        EasyMock.replay(new Object[]{mockBundleContext, mockBundle, mockCurrentManagedArtifacts});
+
+        props.put(DirectoryWatcher.DIR, watchedDirectoryPath);
+
+        dw = new DirectoryWatcher(props, mockBundleContext);
+        dw.noInitialDelay = true;
+        dw.currentManagedArtifacts = mockCurrentManagedArtifacts;
+        dw.scanner = scanner;
+        try {
+            dw.start();
+        }
+        catch(RuntimeException e)
+        {
+            assertEquals(e, expectedException);
+        }
+
+        EasyMock.verify(new Object[]{mockBundleContext, mockBundle, mockCurrentManagedArtifacts});
+    }
+
+    /**
+     * Test the {@link DirectoryWatcher#initializeCurrentManagedBundles()} in conjunction with a opaque Bundle Location.
+     * Assert that a new created {@link Artifact} will be added into the {@link DirectoryWatcher#currentManagedArtifacts}.
+     * 
+     * The {@link DirectoryWatcher#process(java.util.Set)} execution will not be called.
+     * This test breaks the execution in {@link Scanner#initialize(java.util.Map)}.
+     * @throws URISyntaxException 
+     */
+    public void testInitializeCurrentManagedBundlesOpaqueURIOnBundleLocation() throws URISyntaxException
+    {
+        final RuntimeException expectedException = new RuntimeException("expected exception to break execution on defined point.");
+        final File watchedDirectoryFile = new File("src/test/resources/watched");
+        final String watchedDirectoryPath = watchedDirectoryFile.getAbsolutePath();
+
+        final String bundleFileName = "firstjar.jar";
+        final File bundleFile = new File(watchedDirectoryPath,bundleFileName);
+        final String bundleLocation = "blueprint:file:"+watchedDirectoryPath+'/'+bundleFileName+"$Bundle-SymbolicName=foo&Bundle-Version=1.0";
+
+        // break execution
+        Scanner scanner = new Scanner(watchedDirectoryFile)
+        {
+            public void initialize(Map checksums)
+            {
+                throw expectedException;
+            }
+        };
+
+        mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
+        EasyMock.expect(mockBundleContext.getBundles()).andReturn(new Bundle[]{mockBundle});
+        EasyMock.expect(mockBundleContext.getDataFile((String) EasyMock.anyObject())).andReturn(null).anyTimes();
+        EasyMock.expect(mockBundle.getLocation()).andReturn(bundleLocation).anyTimes();
+        Map mockCurrentManagedArtifacts = (Map)EasyMock.createNiceMock(Map.class);
+        EasyMock.expect(mockCurrentManagedArtifacts.put(EasyMock.eq(bundleFile), (Artifact)EasyMock.anyObject())).andReturn(null).times(1);
+
+        EasyMock.replay(new Object[]{mockBundleContext, mockBundle, mockCurrentManagedArtifacts});
+
+        props.put(DirectoryWatcher.DIR, watchedDirectoryPath);
+
+        dw = new DirectoryWatcher(props, mockBundleContext);
+        dw.noInitialDelay = true;
+        dw.currentManagedArtifacts = mockCurrentManagedArtifacts;
+        dw.scanner = scanner;
+        try {
+        dw.start();
+        }
+        catch(RuntimeException e)
+        {
+            assertEquals(e, expectedException);
+        }
+
+        EasyMock.verify(new Object[]{mockBundleContext, mockBundle, mockCurrentManagedArtifacts});
+    }
+
+    /**
+     * Test the {@link DirectoryWatcher#process(java.util.Set) } in conjunction with a opaque Bundle Location.
+     * Assert that no bundle refresh will be called.
+     * @throws URISyntaxException 
+     */
+    public void testProcessOpaqueURIOnBundleLocation() throws URISyntaxException
+    {
+        final RuntimeException expectedException = new RuntimeException("expected exception to break execution on defined point.");
+        final File watchedDirectoryFile = new File("src/test/resources/watched");
+        final String watchedDirectoryPath = watchedDirectoryFile.getAbsolutePath();
+
+        final String bundleFileName = "firstjar.jar";
+        final File bundleFile = new File(watchedDirectoryPath,bundleFileName);
+        final String bundleLocation = "blueprint:file:"+watchedDirectoryPath+'/'+bundleFileName;
+
+        final Scanner scanner = new Scanner(watchedDirectoryFile)
+        {
+            // bypass filesystem scan and return expected bundle file
+            public Set/*<File>*/ scan(boolean reportImmediately)
+            {
+                Set/*<File>*/ fileSet = new HashSet/*<File>*/(1);
+                fileSet.add(bundleFile);
+                return fileSet;
+            }
+        };
+
+        final ArtifactListener mockArtifactListener = (ArtifactListener) EasyMock.createNiceMock(ArtifactListener.class);
+        EasyMock.expect(Boolean.valueOf(mockArtifactListener.canHandle(bundleFile))).andReturn(Boolean.TRUE).anyTimes();
+        final ServiceReference mockServiceReference = (ServiceReference) EasyMock.createNiceMock(ServiceReference.class);
+
+        // simulate known/installed bundles
+        mockBundleContext.addBundleListener((BundleListener) org.easymock.EasyMock.anyObject());
+        EasyMock.expect(mockBundleContext.getBundles()).andReturn(new Bundle[]{mockBundle});
+        EasyMock.expect(mockBundleContext.getDataFile((String) EasyMock.anyObject())).andReturn(null).anyTimes();
+        EasyMock.expect(mockBundle.getLocation()).andReturn(bundleLocation).anyTimes();
+
+        EasyMock.replay(new Object[]{mockBundleContext, mockBundle,mockServiceReference, mockArtifactListener});
+
+        final Artifact artifact = new Artifact();
+        artifact.setBundleId(42);
+        artifact.setChecksum(0);
+        artifact.setListener(mockArtifactListener);
+        artifact.setPath(bundleFile);
+
+        FileInstall.listeners.put(mockServiceReference, mockArtifactListener);
+
+        props.put(DirectoryWatcher.DIR, watchedDirectoryPath);
+
+        dw = new DirectoryWatcher(props, mockBundleContext) {
+
+            void refresh(Bundle[] bundles) throws InterruptedException {
+                Assert.fail("bundle refresh called");
+            }
+            
+        };
+        dw.noInitialDelay = true;
+        // add expected bundle and artifact to the current managed artifacts
+        dw.currentManagedArtifacts.put(bundleFile, artifact);
+        dw.scanner = scanner;
+        try {
+            dw.start();
+        }
+        catch(RuntimeException e)
+        {
+            assertEquals(e, expectedException);
+        }
+
+        EasyMock.verify(new Object[]{mockBundleContext, mockBundle,mockServiceReference, mockArtifactListener});
+    }
 
 }