FELIX-4085 : [Core R5] Implement updates to the Bundle Hook Specification. Apply patch from David Bosschaert

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1550304 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index 7508022..34d600f 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -73,6 +73,7 @@
     private final Map m_cachedHeaders = new HashMap();
     private Map m_uninstalledHeaders = null;
     private long m_cachedHeadersTimestamp;
+    private final Bundle m_installingBundle;
 
     // Indicates whether the bundle is stale, meaning that it has
     // been refreshed and completely removed from the framework.
@@ -94,9 +95,10 @@
         m_stale = false;
         m_activator = null;
         m_context = null;
+        m_installingBundle = null;
     }
 
-    BundleImpl(Felix felix, BundleArchive archive) throws Exception
+    BundleImpl(Felix felix, Bundle installingBundle, BundleArchive archive) throws Exception
     {
         __m_felix = felix;
         m_archive = archive;
@@ -105,6 +107,7 @@
         m_stale = false;
         m_activator = null;
         m_context = null;
+        m_installingBundle = installingBundle;
 
         BundleRevision revision = createRevision(false);
         addRevision(revision);
@@ -1273,9 +1276,21 @@
                         CollisionHook ch = getFramework().getService(getFramework(), hook);
                         if (ch != null)
                         {
-                            Felix.m_secureAction.invokeBundleCollisionHook(ch,
-                                isUpdate ? CollisionHook.UPDATING : CollisionHook.INSTALLING,
-                                this, shrinkableCollisionCandidates);
+                            int operationType;
+                            Bundle target;
+                            if (isUpdate)
+                            {
+                                operationType = CollisionHook.UPDATING;
+                                target = this;
+                            }
+                            else
+                            {
+                                operationType = CollisionHook.INSTALLING;
+                                target = m_installingBundle == null ? this : m_installingBundle;
+                            }
+
+                            Felix.m_secureAction.invokeBundleCollisionHook(ch, operationType, target,
+                                    shrinkableCollisionCandidates);
                         }
                     }
                 }
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index b184120..e4dc4f7 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -2790,7 +2790,7 @@
             }
             try
             {
-                bundle = new BundleImpl(this, ba);
+                bundle = new BundleImpl(this, null, ba);
 
                 // Extensions are handled as a special case.
                 if (bundle.isExtension())
@@ -2902,7 +2902,7 @@
                     }
                     try
                     {
-                        bundle = new BundleImpl(this, ba);
+                        bundle = new BundleImpl(this, origin, ba);
                     }
                     finally
                     {
diff --git a/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java b/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java
index 3ecbfdb..5b367cb 100644
--- a/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java
@@ -39,10 +39,11 @@
     public void testCollisionHookInstall() throws Exception {
         BundleImpl identicalBundle = mockBundleImpl(1L, "foo", "1.2.1.a");
         BundleImpl differentBundle = mockBundleImpl(2L, "bar", "1.2.1.a");
+        BundleImpl originatingBundle = mockBundleImpl(4L, "xyz", "1.0.0");
 
         CollisionHook testCollisionHook = new CollisionHook() {
             public void filterCollisions(int operationType, Bundle target, Collection<Bundle> collisionCandidates) {
-                if ((target.getBundleId() == 3L) && (operationType == CollisionHook.INSTALLING)) {
+                if ((target.getBundleId() == 4L) && (operationType == CollisionHook.INSTALLING)) {
                     collisionCandidates.clear();
                 }
             }
@@ -72,7 +73,7 @@
         Mockito.when(archive.getCurrentRevision()).thenReturn(archiveRevision);
         Mockito.when(archive.getId()).thenReturn(3L);
 
-        BundleImpl bi = new BundleImpl(felixMock, archive);
+        BundleImpl bi = new BundleImpl(felixMock, originatingBundle, archive);
         assertEquals(3L, bi.getBundleId());
 
         // Do the revise operation.
@@ -125,7 +126,7 @@
         Mockito.when(archive.getCurrentRevision()).thenReturn(archiveRevision);
         Mockito.when(archive.getId()).thenReturn(3L);
 
-        BundleImpl bi = new BundleImpl(felixMock, archive);
+        BundleImpl bi = new BundleImpl(felixMock, null, archive);
         assertEquals("zar", bi.getSymbolicName());
 
         // Do the revise operation, change the bsn to foo
@@ -175,7 +176,7 @@
         Mockito.when(archive.getId()).thenReturn(3L);
 
         try {
-            new BundleImpl(felixMock, archive);
+            new BundleImpl(felixMock, null, archive);
             fail("Should have thrown a BundleException because the collision hook is not enabled");
         } catch (BundleException be) {
             // good
@@ -210,7 +211,7 @@
         Mockito.when(archive.getCurrentRevision()).thenReturn(archiveRevision);
         Mockito.when(archive.getId()).thenReturn(3L);
 
-        BundleImpl bi = new BundleImpl(felixMock, archive);
+        BundleImpl bi = new BundleImpl(felixMock, null, archive);
         assertEquals(3L, bi.getBundleId());
     }
 
@@ -238,7 +239,7 @@
         Mockito.when(archive.getId()).thenReturn(3L);
 
         try {
-            new BundleImpl(felixMock, archive);
+            new BundleImpl(felixMock, null, archive);
             fail("Should have thrown a BundleException because the installed bundle is not unique");
         } catch (BundleException be) {
             // good