You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2009/06/10 23:15:12 UTC

svn commit: r783522 - in /felix/trunk/framework/src/main/java/org/apache/felix/framework: BundleImpl.java Felix.java ModuleImpl.java StartLevelImpl.java util/EventDispatcher.java

Author: rickhall
Date: Wed Jun 10 21:15:12 2009
New Revision: 783522

URL: http://svn.apache.org/viewvc?rev=783522&view=rev
Log:
More modifications for activation policies. (FELIX-749)

Modified:
    felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java?rev=783522&r1=783521&r2=783522&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java Wed Jun 10 21:15:12 2009
@@ -38,7 +38,7 @@
     private final BundleArchive m_archive;
     private IModule[] m_modules = new IModule[0];
     private volatile int m_state;
-    private int m_runtimeActivationPolicy;
+    private boolean m_useDeclaredActivationPolicy;
     private BundleActivator m_activator = null;
     private BundleContext m_context = null;
     private final Map m_cachedHeaders = new HashMap();
@@ -63,7 +63,7 @@
         __m_felix = null;
         m_archive = null;
         m_state = Bundle.INSTALLED;
-        m_runtimeActivationPolicy = 0;
+        m_useDeclaredActivationPolicy = false;
         m_stale = false;
         m_activator = null;
         m_context = null;
@@ -74,7 +74,7 @@
         __m_felix = felix;
         m_archive = archive;
         m_state = Bundle.INSTALLED;
-        m_runtimeActivationPolicy = 0;
+        m_useDeclaredActivationPolicy = false;
         m_stale = false;
         m_activator = null;
         m_context = null;
@@ -131,16 +131,14 @@
         }
     }
 
-    synchronized int getRuntimeActivationPolicy()
+    synchronized boolean isDeclaredActivationPolicyUsed()
     {
-        return (m_runtimeActivationPolicy == IModule.EAGER_ACTIVATION)
-            ? IModule.EAGER_ACTIVATION
-            : getCurrentModule().getDeclaredActivationPolicy();
+        return m_useDeclaredActivationPolicy;
     }
 
-    synchronized void setRuntimeActivationPolicy(int policy)
+    synchronized void setDeclaredActivationPolicyUsed(boolean b)
     {
-        m_runtimeActivationPolicy = policy;
+        m_useDeclaredActivationPolicy = b;
     }
 
     synchronized BundleActivator getActivator()

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=783522&r1=783521&r2=783522&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Wed Jun 10 21:15:12 2009
@@ -1004,8 +1004,9 @@
                         }
                     }
                     // Stop the bundle if necessary.
-                    else if ((impl.getState() == Bundle.ACTIVE) &&
-                        (impl.getStartLevel(getInitialBundleStartLevel())
+                    else if (((impl.getState() == Bundle.ACTIVE)
+                        || (impl.getState() == Bundle.STARTING))
+                        && (impl.getStartLevel(getInitialBundleStartLevel())
                             > getActiveStartLevel()))
                     {
                         try
@@ -1145,7 +1146,6 @@
                 try
                 {
                     // Start the bundle if necessary.
-                    // Start the bundle if necessary.
                     if (((impl.getPersistentState() == Bundle.ACTIVE)
                         || (impl.getPersistentState() == Bundle.STARTING))
                         && (impl.getStartLevel(getInitialBundleStartLevel())
@@ -1159,8 +1159,9 @@
                         startBundle(impl, options);
                     }
                     // Stop the bundle if necessary.
-                    else if ((impl.getState() == Bundle.ACTIVE) &&
-                        (impl.getStartLevel(getInitialBundleStartLevel())
+                    else if (((impl.getState() == Bundle.ACTIVE)
+                        || (impl.getState() == Bundle.STARTING))
+                        && (impl.getStartLevel(getInitialBundleStartLevel())
                             > getActiveStartLevel()))
                     {
                         stopBundle(impl, false);
@@ -1209,6 +1210,25 @@
             || (((BundleImpl) bundle).getPersistentState() == Bundle.STARTING);
     }
 
+    /**
+     * Returns whether the bundle is using its declared activation policy;
+     * this is an method implementation for the Start Level service.
+     * @param bundle The bundle to examine.
+     * @return <tt>true</tt> if the bundle is using its declared activation
+     *         policy, <tt>false</tt> otherwise.
+     * @throws java.lang.IllegalArgumentException If the specified
+     *          bundle has been uninstalled.
+    **/
+    boolean isBundleActivationPolicyUsed(Bundle bundle)
+    {
+        if (bundle.getState() == Bundle.UNINSTALLED)
+        {
+            throw new IllegalArgumentException("Bundle is uninstalled.");
+        }
+
+        return ((BundleImpl) bundle).isDeclaredActivationPolicyUsed();
+    }
+
     //
     // Implementation of Bundle interface methods.
     //
@@ -1386,6 +1406,8 @@
         // that case, the global lock will be acquired to make sure no
         // bundles can be installed or uninstalled during the resolve.
 
+        int eventType;
+
         // Acquire bundle lock.
         try
         {
@@ -1405,11 +1427,9 @@
             }
         }
 
-        // Set the bundl
-        bundle.setRuntimeActivationPolicy(
-            ((options & Bundle.START_ACTIVATION_POLICY) > 0)
-            ? IModule.LAZY_ACTIVATION
-            : IModule.EAGER_ACTIVATION);
+        // Record whether the bundle is using its declared activation policy.
+        bundle.setDeclaredActivationPolicyUsed(
+            (options & Bundle.START_ACTIVATION_POLICY) != 0);
 
         try
         {
@@ -1473,25 +1493,35 @@
                     resolveBundle(bundle);
                     // No break.
                 case Bundle.RESOLVED:
-                    setBundleStateAndNotify(bundle, Bundle.STARTING);
-                    fireBundleEvent(BundleEvent.STARTING, bundle);
                     break;
             }
 
             // Set the bundle's context.
             bundle.setBundleContext(new BundleContextImpl(m_logger, this, bundle));
 
+            // At this point, no matter if the bundle's activation policy is
+            // eager or deferred, we need to set the bundle's state to STARTING.
+            // We don't fire a BundleEvent here for this state change, since
+            // STARTING events are only fired if we are invoking the activator,
+            // which we may not do if activation is deferred.
+            setBundleStateAndNotify(bundle, Bundle.STARTING);
+
             // If the bundle's activation policy is eager or activation has already
             // been triggered, then activate the bundle immediately.
-            if ((bundle.getRuntimeActivationPolicy() != IModule.LAZY_ACTIVATION)
+            if (!bundle.isDeclaredActivationPolicyUsed()
+                || (bundle.getCurrentModule().getDeclaredActivationPolicy() != IModule.LAZY_ACTIVATION)
                 || ((ModuleImpl) bundle.getCurrentModule()).isActivationTrigger())
             {
-                activateBundle(bundle);
+                // Record the event type for the final event and activate.
+                eventType = BundleEvent.STARTED;
+                // Note that the STARTING event is thrown in the activateBundle() method.
+                activateBundle(bundle, false);
             }
             // Otherwise, defer bundle activation.
             else
             {
-                setBundleStateAndNotify(bundle, Bundle.STARTING);
+                // Record the event type for the final event.
+                eventType = BundleEvent.LAZY_ACTIVATION;
             }
 
             // We still need to fire the STARTED event, but we will do
@@ -1503,13 +1533,12 @@
             releaseBundleLock(bundle);
         }
 
-        // If there was no exception, then we should fire the STARTED event
-        // here without holding the lock.
-// TODO: LAZY - WE SHOULD REALLY BE FIRING EVENT HERE, OUTSIDE OF LOCK.
-//        fireBundleEvent(BundleEvent.STARTED, bundle);
+        // If there was no exception, then we should fire the STARTED
+        // or LAZY_ACTIVATION event here without holding the lock.
+        fireBundleEvent(eventType, bundle);
     }
 
-    public void activateBundle(BundleImpl bundle) throws BundleException
+    void activateBundle(BundleImpl bundle, boolean fireEvent) throws BundleException
     {
         // CONCURRENCY NOTE:
         // We will first acquire the bundle lock for the specific bundle
@@ -1538,6 +1567,9 @@
                 return;
             }
 
+            // Fire STARTING event to signify call to bundle activator.
+            fireBundleEvent(BundleEvent.STARTING, bundle);
+
             try
             {
                 // Set the bundle's activator.
@@ -1603,10 +1635,15 @@
             releaseBundleLock(bundle);
         }
 
-        // If there was no exception, then we should fire the STARTED event
-        // here without holding the lock.
-// TODO: LAZY - WE COULD BE HOLDING THE LOCK FROM startBundle() ABOVE.
-        fireBundleEvent(BundleEvent.STARTED, bundle);
+        // If there was no exception, then we should fire the STARTED
+        // event here without holding the lock if specified.
+        // TODO: LAZY - It would be nice to figure out how to do this without
+        //       duplicating code; this method is called from two different
+        //       places -- one fires the event itself the other one needs it.
+        if (fireEvent)
+        {
+            fireBundleEvent(BundleEvent.STARTED, bundle);
+        }
     }
 
     void updateBundle(BundleImpl bundle, InputStream is)
@@ -1876,6 +1913,15 @@
                 bundle.setPersistentStateInactive();
             }
 
+            // If the bundle is not persistently started, then we
+            // need to reset the activation policy flag, since it
+            // does not persist across persistent stops or transient
+            // stops.
+            if (!isBundlePersistentlyStarted(bundle))
+            {
+                bundle.setDeclaredActivationPolicyUsed(false);
+            }
+
             // As per the OSGi spec, fragment bundles can not be stopped and must
             // throw a BundleException when there is an attempt to stop one.
             if (Util.isFragment(bundle.getCurrentModule()))
@@ -1883,12 +1929,14 @@
                 throw new BundleException("Fragment bundles can not be stopped: " + bundle);
             }
 
+            boolean wasActive = false;
             switch (bundle.getState())
             {
                 case Bundle.UNINSTALLED:
                     throw new IllegalStateException("Cannot stop an uninstalled bundle.");
                 case Bundle.STARTING:
-                    if (bundle.getRuntimeActivationPolicy() != IModule.LAZY_ACTIVATION)
+                    if (bundle.isDeclaredActivationPolicyUsed()
+                        && bundle.getCurrentModule().getDeclaredActivationPolicy() != IModule.LAZY_ACTIVATION)
                     {
                         throw new BundleException(
                             "Stopping a starting or stopping bundle is currently not supported.");
@@ -1901,13 +1949,18 @@
                 case Bundle.RESOLVED:
                     return;
                 case Bundle.ACTIVE:
-                    // Set bundle state..
-                    setBundleStateAndNotify(bundle, Bundle.STOPPING);
-                    fireBundleEvent(BundleEvent.STOPPING, bundle);
+                    wasActive = true;
                     break;
             }
 
-            if (bundle.getState() != Bundle.STARTING)
+            // At this point, no matter if the bundle's activation policy is
+            // eager or deferred, we need to set the bundle's state to STOPPING
+            // and fire the STOPPING event.
+            setBundleStateAndNotify(bundle, Bundle.STOPPING);
+            fireBundleEvent(BundleEvent.STOPPING, bundle);
+
+            // If the bundle was active, then invoke the activator stop() method.
+            if (wasActive)
             {
                 try
                 {

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java?rev=783522&r1=783521&r2=783522&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java Wed Jun 10 21:15:12 2009
@@ -1549,7 +1549,10 @@
 
                         if (clazz == null)
                         {
-                            int activationPolicy = ((BundleImpl) getBundle()).getRuntimeActivationPolicy();
+                            int activationPolicy = 
+                                ((BundleImpl) getBundle()).isDeclaredActivationPolicyUsed()
+                                ? ((BundleImpl) getBundle()).getCurrentModule().getDeclaredActivationPolicy()
+                                : IModule.EAGER_ACTIVATION;
 
                             // If the module is using deferred activation, then if
                             // we load this class from this module we need to activate
@@ -1645,7 +1648,7 @@
                             try
                             {
                                 ((BundleImpl) ((Object[]) deferredList.get(i))[1]).getFramework().activateBundle(
-                                    (BundleImpl) ((Object[]) deferredList.get(i))[1]);
+                                    (BundleImpl) ((Object[]) deferredList.get(i))[1], true);
                             }
                             catch (BundleException ex)
                             {

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java?rev=783522&r1=783521&r2=783522&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java Wed Jun 10 21:15:12 2009
@@ -215,7 +215,7 @@
     **/
 	public boolean isBundleActivationPolicyUsed(Bundle bundle)
     {
-        throw new UnsupportedOperationException("This feature has not yet been implemented.");
+        return m_felix.isBundleActivationPolicyUsed(bundle);
     }
 
     public void run()

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java?rev=783522&r1=783521&r2=783522&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java Wed Jun 10 21:15:12 2009
@@ -595,13 +595,15 @@
             syncListeners = m_syncBundleListeners;
         }
 
+System.out.println("+++ FIRING BUNDLE EVENT " + event.getType() + " FROM " + event.getBundle().getSymbolicName());
         // Fire synchronous bundle listeners immediately on the calling thread.
         fireEventImmediately(m_logger, Request.BUNDLE_EVENT, syncListeners, event);
 
         // The spec says that asynchronous bundle listeners do not get events
-        // of types STARTING or STOPPING.
+        // of types STARTING, STOPPING, or LAZY_ACTIVATION.
         if ((event.getType() != BundleEvent.STARTING) &&
-            (event.getType() != BundleEvent.STOPPING))
+            (event.getType() != BundleEvent.STOPPING) &&
+            (event.getType() != BundleEvent.LAZY_ACTIVATION))
         {
             // Fire asynchronous bundle listeners on a separate thread.
             fireEventAsynchronously(m_logger, Request.BUNDLE_EVENT, listeners, event);