Bug 419068: Support (degraded) use of sisu-plexus with guice 3.0
diff --git a/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/PlexusBindingModule.java b/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/PlexusBindingModule.java
index 137b79a..1742cd5 100644
--- a/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/PlexusBindingModule.java
+++ b/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/PlexusBindingModule.java
@@ -19,7 +19,6 @@
 import com.google.inject.Binder;
 import com.google.inject.Module;
 import com.google.inject.matcher.Matchers;
-import com.google.inject.spi.ProvisionListener;
 
 /**
  * Guice {@link Module} that supports registration, injection, and management of Plexus beans.
@@ -70,9 +69,9 @@
         // attach custom logic to support Plexus requirements/configuration/lifecycle
         final PlexusBeanBinder plexusBinder = new PlexusBeanBinder( manager, sources );
         binder.bindListener( Matchers.any(), new BeanListener( plexusBinder ) );
-        if ( manager instanceof ProvisionListener )
+        if ( manager instanceof Module )
         {
-            binder.bindListener( Matchers.any(), (ProvisionListener) manager );
+            ( (Module) manager ).configure( binder );
         }
     }
 }
diff --git a/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/PlexusLifecycleManager.java b/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/PlexusLifecycleManager.java
index f0dc25a..a726794 100644
--- a/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/PlexusLifecycleManager.java
+++ b/org.eclipse.sisu.plexus/src/org/eclipse/sisu/plexus/PlexusLifecycleManager.java
@@ -30,21 +30,43 @@
 import org.eclipse.sisu.bean.PropertyBinding;
 import org.eclipse.sisu.inject.Logs;
 
-import com.google.inject.spi.ProvisionListener;
+import com.google.inject.Binder;
+import com.google.inject.Module;
+import com.google.inject.matcher.Matchers;
 
 /**
  * {@link PlexusBeanManager} that manages Plexus components requiring lifecycle management.
  */
 public final class PlexusLifecycleManager
-    implements PlexusBeanManager, ProvisionListener
+    implements PlexusBeanManager, Module
 {
     // ----------------------------------------------------------------------
+    // Static initialization
+    // ----------------------------------------------------------------------
+
+    static
+    {
+        boolean hasProvisionListener;
+        try
+        {
+            hasProvisionListener = com.google.inject.spi.ProvisionListener.class.isInterface();
+        }
+        catch ( final LinkageError e )
+        {
+            hasProvisionListener = false;
+        }
+        HAS_PROVISION_LISTENER = hasProvisionListener;
+    }
+
+    // ----------------------------------------------------------------------
     // Constants
     // ----------------------------------------------------------------------
 
     private static final Class<?>[] LIFECYCLE_TYPES = { LogEnabled.class, Contextualizable.class, Initializable.class,
         Startable.class, Disposable.class };
 
+    private static final boolean HAS_PROVISION_LISTENER;
+
     // ----------------------------------------------------------------------
     // Implementation fields
     // ----------------------------------------------------------------------
@@ -80,6 +102,14 @@
     // Public methods
     // ----------------------------------------------------------------------
 
+    public void configure( final Binder binder )
+    {
+        if ( HAS_PROVISION_LISTENER )
+        {
+            binder.bindListener( Matchers.any(), new PlexusProvisionListener() );
+        }
+    }
+
     public boolean manage( final Class<?> clazz )
     {
         for ( final Class<?> lifecycleType : LIFECYCLE_TYPES )
@@ -121,30 +151,6 @@
         return null;
     }
 
-    public <T> void onProvision( final ProvisionInvocation<T> pi )
-    {
-        final List<?>[] holder = getPendingHolder();
-        if ( null == holder[0] )
-        {
-            List<?> beans;
-            holder[0] = Collections.EMPTY_LIST;
-            try
-            {
-                pi.provision();
-            }
-            finally
-            {
-                beans = holder[0];
-                holder[0] = null;
-            }
-
-            for ( int i = 0, size = beans.size(); i < size; i++ )
-            {
-                manageLifecycle( beans.get( i ) );
-            }
-        }
-    }
-
     @SuppressWarnings( { "rawtypes", "unchecked" } )
     public boolean manage( final Object bean )
     {
@@ -158,13 +164,20 @@
         }
         if ( bean instanceof Contextualizable || bean instanceof Initializable || bean instanceof Startable )
         {
-            final List<?>[] holder = getPendingHolder();
-            List beans = holder[0];
-            if ( null == beans || beans.isEmpty() )
+            if ( HAS_PROVISION_LISTENER )
             {
-                holder[0] = beans = new ArrayList<Object>();
+                final List<?>[] holder = getPendingHolder();
+                List beans = holder[0];
+                if ( null == beans || beans.isEmpty() )
+                {
+                    holder[0] = beans = new ArrayList<Object>();
+                }
+                beans.add( bean );
             }
-            beans.add( bean );
+            else
+            {
+                manageLifecycle( bean );
+            }
         }
         return true;
     }
@@ -231,11 +244,7 @@
         }
     }
 
-    // ----------------------------------------------------------------------
-    // Implementation methods
-    // ----------------------------------------------------------------------
-
-    private List<?>[] getPendingHolder()
+    List<?>[] getPendingHolder()
     {
         List<?>[] holder = pendingHolder.get();
         if ( null == holder )
@@ -245,36 +254,7 @@
         return holder;
     }
 
-    private static <T> boolean synchronizedAdd( final List<T> list, final T element )
-    {
-        synchronized ( list )
-        {
-            return list.add( element );
-        }
-    }
-
-    private static boolean synchronizedRemove( final List<?> list, final Object element )
-    {
-        synchronized ( list )
-        {
-            return list.remove( element );
-        }
-    }
-
-    private static <T> T synchronizedRemoveLast( final List<T> list )
-    {
-        synchronized ( list )
-        {
-            final int size = list.size();
-            if ( size > 0 )
-            {
-                return list.remove( size - 1 );
-            }
-            return null;
-        }
-    }
-
-    private void manageLifecycle( final Object bean )
+    void manageLifecycle( final Object bean )
     {
         final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
         try
@@ -314,6 +294,39 @@
         }
     }
 
+    // ----------------------------------------------------------------------
+    // Implementation methods
+    // ----------------------------------------------------------------------
+
+    private static <T> boolean synchronizedAdd( final List<T> list, final T element )
+    {
+        synchronized ( list )
+        {
+            return list.add( element );
+        }
+    }
+
+    private static boolean synchronizedRemove( final List<?> list, final Object element )
+    {
+        synchronized ( list )
+        {
+            return list.remove( element );
+        }
+    }
+
+    private static <T> T synchronizedRemoveLast( final List<T> list )
+    {
+        synchronized ( list )
+        {
+            final int size = list.size();
+            if ( size > 0 )
+            {
+                return list.remove( size - 1 );
+            }
+            return null;
+        }
+    }
+
     private void contextualize( final Contextualizable bean )
     {
         Logs.trace( "Contextualize: <>", bean, null );
@@ -420,4 +433,36 @@
             }
         }
     }
+
+    // ----------------------------------------------------------------------
+    // Implementation types
+    // ----------------------------------------------------------------------
+
+    final class PlexusProvisionListener
+        implements com.google.inject.spi.ProvisionListener
+    {
+        public <T> void onProvision( final ProvisionInvocation<T> pi )
+        {
+            final List<?>[] holder = getPendingHolder();
+            if ( null == holder[0] )
+            {
+                List<?> beans;
+                holder[0] = Collections.EMPTY_LIST;
+                try
+                {
+                    pi.provision();
+                }
+                finally
+                {
+                    beans = holder[0];
+                    holder[0] = null;
+                }
+
+                for ( int i = 0, size = beans.size(); i < size; i++ )
+                {
+                    manageLifecycle( beans.get( i ) );
+                }
+            }
+        }
+    }
 }