FELIX-4724 Separate transform state behavior (bytes and import lists made immutable) from define behavior (set classname).

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1643495 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
index 8106b74..9c9b09b 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
@@ -2094,9 +2094,11 @@
                         } 
                         catch (Error e)
                         {
-                          wci.setState(WovenClass.TRANSFORMING_FAILED);
-                          callWovenClassListeners(felix, wovenClassListeners, wci);
-                          throw e;
+                            // Mark the woven class as incomplete.
+                            wci.complete(null, null, null);
+                            wci.setState(WovenClass.TRANSFORMING_FAILED);
+                            callWovenClassListeners(felix, wovenClassListeners, wci);
+                            throw e;
                         }
                     }
                     // Before we actually attempt to define the class, grab
@@ -2139,6 +2141,7 @@
                             wci.setState(WovenClass.DEFINE_FAILED);
                             callWovenClassListeners(felix, wovenClassListeners, wci);
                         }
+                        throw e;
                     }
 
                     // Perform deferred activation without holding the class loader lock,
@@ -2353,6 +2356,7 @@
                         }
                         if(wci != null)
                         {
+                            wci.completeDefine(clazz);
                             wci.setState(WovenClass.DEFINED);
                             callWovenClassListeners(felix, wovenClassListeners, wci);
                         }
@@ -2368,15 +2372,6 @@
             }
             finally
             {
-                // If we have a woven class, mark it as complete.
-                // Not exactly clear how we should deal with the
-                // case where the weaving didn't happen because
-                // someone else beat us in defining the class.
-                if (wci != null)
-                {
-                    wci.complete(clazz, bytes, wci.getDynamicImportsInternal());
-                }
-
                 synchronized (lock)
                 {
                     m_classLocks.remove(name);
@@ -2420,8 +2415,6 @@
                                     sr.getBundle(),
                                     th);
 
-                            // Mark the woven class as incomplete.
-                            wci.complete(null, null, null);
                             // Throw class format exception per spec.
                             Error error = new ClassFormatError("Weaving hook failed.");
                             error.initCause(th);
diff --git a/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java b/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java
index b929cd3..07b7bb7 100644
--- a/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/WovenClassImpl.java
@@ -54,11 +54,21 @@
     synchronized void complete(Class definedClass, byte[] bytes,
             List<String> imports)
     {
-        m_definedClass = definedClass;
+        completeDefine(definedClass);
         m_bytes = (bytes == null) ? m_bytes : bytes;
+        completeImports(imports);
+    }
+    
+    synchronized void completeImports(List<String> imports)
+    {
         m_imports = (imports == null) ? ImmutableList.newInstance(m_imports)
                 : ImmutableList.newInstance(imports);
     }
+    
+    synchronized void completeDefine(Class definedClass)
+    {
+        m_definedClass = definedClass;
+    }
 
     public synchronized byte[] getBytes()
     {
@@ -85,7 +95,7 @@
             sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
                     AdminPermission.WEAVE));
         }
-        if (m_isComplete)
+        if (m_state >= TRANSFORMED)
         {
             throw new IllegalStateException(
                     "Cannot change bytes after class weaving is completed.");
@@ -403,6 +413,10 @@
         {
             m_isComplete = true;
         }
+        if(state == TRANSFORMED)
+        {
+            completeImports(null);
+        }
         m_state = state;
     }
 
diff --git a/framework/src/test/java/org/apache/felix/framework/BundleWiringImplTest.java b/framework/src/test/java/org/apache/felix/framework/BundleWiringImplTest.java
index cf570e5..a2ddf68 100644
--- a/framework/src/test/java/org/apache/felix/framework/BundleWiringImplTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/BundleWiringImplTest.java
@@ -350,9 +350,10 @@
         {

 

             bundleClassLoader.findClass(TestClass.class.getName());

-        } catch (ClassNotFoundException e)

+            fail("Class should throw exception");

+        } catch (Throwable e)

         {

-            fail("Class should not throw exception");

+            

         }

         assertEquals("There should be 2 state changes fired by the weaving", 2,

                 dummyWovenClassListener.stateList.size());