geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ga...@apache.org
Subject svn commit: r771173 - in /geronimo/sandbox/blueprint/blueprint-core/src: main/java/org/apache/geronimo/blueprint/ main/java/org/apache/geronimo/blueprint/context/ test/java/org/apache/geronimo/blueprint/
Date Mon, 04 May 2009 04:49:00 GMT
Author: gawor
Date: Mon May  4 04:48:58 2009
New Revision: 771173

URL: http://svn.apache.org/viewvc?rev=771173&view=rev
Log:
get lazy activation working

Added:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/TriggerService.java
  (with props)
Modified:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/BlueprintExtender.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintObjectRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceRegistrationProxy.java
    geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/TestBlueprintContext.java

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/BlueprintExtender.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/BlueprintExtender.java?rev=771173&r1=771172&r2=771173&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/BlueprintExtender.java
(original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/BlueprintExtender.java
Mon May  4 04:48:58 2009
@@ -67,7 +67,7 @@
         Bundle[] bundles = context.getBundles();
         for (Bundle b : bundles) {
             if (b.getState() == Bundle.ACTIVE) {
-                checkBundle(b);
+                checkBundle(b, false);
             }
         }
         LOGGER.debug("Blueprint extender started");
@@ -88,10 +88,18 @@
     }
 
     public void bundleChanged(BundleEvent event) {
-        if (event.getType() == BundleEvent.STARTED) {
-            checkBundle(event.getBundle());
+        Bundle bundle = event.getBundle();
+        if (event.getType() == BundleEvent.LAZY_ACTIVATION) {
+            checkBundle(bundle, true);
+        } else if (event.getType() == BundleEvent.STARTED) {
+            BlueprintContextImpl blueprintContext = contextMap.get(bundle);
+            if (blueprintContext == null) {
+                checkBundle(bundle, false);
+            } else {
+                blueprintContext.triggerActivation();
+            }
         } else if (event.getType() == BundleEvent.STOPPING) {
-            destroyContext(event.getBundle());
+            destroyContext(bundle);
         }
     }
 
@@ -103,8 +111,8 @@
         }
     }
     
-    private void checkBundle(Bundle bundle) {
-        LOGGER.debug("Scanning bundle {} for blueprint application", bundle.getSymbolicName());
+    private void checkBundle(Bundle bundle, boolean lazyActivation) {
+        LOGGER.debug("Scanning bundle {} for blueprint application (lazy: {})", bundle.getSymbolicName(),
lazyActivation);
 
         List<URL> urls = new ArrayList<URL>();
         Dictionary headers = bundle.getHeaders();
@@ -119,7 +127,7 @@
             }
         }
         if (urls.isEmpty()) {
-            Enumeration e = bundle.findEntries("OSGI-INF/blueprint", "*.xml", true);
+            Enumeration e = bundle.findEntries("OSGI-INF/blueprint", "*.xml", false);
             if (e != null) {
                 while (e.hasMoreElements()) {
                     URL u = (URL) e.nextElement();
@@ -130,20 +138,20 @@
         if (!urls.isEmpty()) {
             LOGGER.debug("Found blueprint application in bundle {} with urls: {}", bundle.getSymbolicName(),
urls);
 
-            // Check compatibility
-            boolean compatible;
-            try {
-                Class clazz = bundle.getBundleContext().getBundle().loadClass(BlueprintContext.class.getName());
-                compatible = (clazz == BlueprintContext.class);
-            } catch (ClassNotFoundException e) {
-                compatible = true;
-            }
+            // Check compatibility 
+            // XXX: we can't check compatibility when dealing with lazy activated bundles
since that will trigger
+            // the bundle to be fully started
+            boolean compatible = lazyActivation || isCompatible(bundle);
             if (compatible) {
-                final BlueprintContextImpl blueprintContext = new BlueprintContextImpl(bundle.getBundleContext(),
sender, handlers, executors, urls);
+                final BlueprintContextImpl blueprintContext = new BlueprintContextImpl(bundle.getBundleContext(),
sender, handlers, executors, urls, lazyActivation);
                 contextMap.put(bundle, blueprintContext);
-                executors.submit(blueprintContext);
+                if (lazyActivation) {
+                    blueprintContext.run();
+                } else {
+                    executors.submit(blueprintContext);
+                }
             } else {
-                LOGGER.info("Bundle {} is not compatible with this blueprint extender", bundle.getSymbolicName());
+                LOGGER.debug("Bundle {} is not compatible with this blueprint extender",
bundle.getSymbolicName());
             }
 
         } else {
@@ -151,5 +159,15 @@
         }
     }
 
-
+    private boolean isCompatible(Bundle bundle) {
+        // Check compatibility
+        boolean compatible;
+        try {
+            Class clazz = bundle.getBundleContext().getBundle().loadClass(BlueprintContext.class.getName());
+            compatible = (clazz == BlueprintContext.class);
+        } catch (ClassNotFoundException e) {
+            compatible = true;
+        }
+        return compatible;
+    }
 }

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java?rev=771173&r1=771172&r2=771173&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java
(original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintContextImpl.java
Mon May  4 04:48:58 2009
@@ -51,6 +51,7 @@
 import org.apache.xbean.recipe.DefaultExecutionContext;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.blueprint.context.BlueprintContext;
@@ -81,6 +82,8 @@
         Populated,
         WaitForInitialReferences,
         InitialReferencesSatisfied,
+        WaitForTrigger,
+        Create,
         Created,
         Failed
     }
@@ -89,6 +92,7 @@
     private final BlueprintContextEventSender sender;
     private final NamespaceHandlerRegistry handlers;
     private final List<URL> urls;
+    private final boolean lazyActivation;
     private final ComponentDefinitionRegistryImpl helperComponentDefinitionRegistry;
     private final ComponentDefinitionRegistryImpl componentDefinitionRegistry;
     private final ConversionServiceImpl conversionService;
@@ -101,8 +105,10 @@
     private boolean waitForNamespaceHandlersEventSent;
     private Map<String, Destroyable> destroyables = new HashMap<String, Destroyable>();
     private Map<String, List<SatisfiableRecipe>> satisfiables;
+    private boolean serviceActivation;
+    private Map<ServiceMetadata, TriggerService> triggerServices;
 
-    public BlueprintContextImpl(BundleContext bundleContext, BlueprintContextEventSender
sender, NamespaceHandlerRegistry handlers, ExecutorService executors, List<URL> urls)
{
+    public BlueprintContextImpl(BundleContext bundleContext, BlueprintContextEventSender
sender, NamespaceHandlerRegistry handlers, ExecutorService executors, List<URL> urls,
boolean lazyActivation) {
         this.bundleContext = bundleContext;
         this.sender = sender;
         this.handlers = handlers;
@@ -111,6 +117,8 @@
         this.helperComponentDefinitionRegistry = new ComponentDefinitionRegistryImpl();
         this.componentDefinitionRegistry = new ComponentDefinitionRegistryImpl();
         this.executors = executors;
+        this.lazyActivation = lazyActivation;
+        this.triggerServices = new HashMap<ServiceMetadata, TriggerService>();
     }
 
     public Class loadClass(String name) throws ClassNotFoundException {
@@ -198,6 +206,16 @@
                             return;
                         }
                     case InitialReferencesSatisfied:
+                        if (lazyActivation) {
+                            registerTriggerServices();
+                            state = State.WaitForTrigger;                            
+                        } else {
+                            state = State.Create;
+                        }
+                        break;
+                    case WaitForTrigger:
+                        return;
+                    case Create:
                         instantiateComponents();
                         registerAllServices();
 
@@ -394,6 +412,50 @@
             }
         }
     }
+        
+    private void registerTriggerServices() {
+        for (ServiceMetadata service : getExportedServicesMetadata()) {
+            // Trigger services are only created for services without listeners and explicitly
defined interface classes
+            if (service.getRegistrationListeners().isEmpty() && !service.getInterfaceNames().isEmpty())
{
+                TriggerService triggerService = new TriggerService(service, this);
+                triggerService.register();
+                triggerServices.put(service, triggerService);
+            }
+        }
+    }
+    
+    private void unregisterTriggerServices() {
+        for (TriggerService service : triggerServices.values()) {
+            service.unregister();
+        }
+        triggerServices.clear();
+    }
+        
+    protected TriggerService removeTriggerService(ServiceMetadata metadata) {
+        return triggerServices.remove(metadata);
+    }
+    
+    protected void forceActivation(boolean serviceActivation) throws BundleException {
+        this.serviceActivation = serviceActivation;
+        getBundleContext().getBundle().start(Bundle.START_TRANSIENT);
+    }
+    
+    public synchronized void triggerActivation() {
+        if (!lazyActivation) {
+            throw new IllegalStateException("triggerActivation can only be called for bundles
with lazy activation policy");
+        }
+        if (state == State.WaitForTrigger) {
+            LOGGER.debug("Activation triggered (service activation: {})", serviceActivation);

+            state = State.Create;
+            if (serviceActivation) {
+                // service triggered activation runs synchronously
+                run();
+            } else {
+                // classloader triggered activation runs asynchronously
+                executors.submit(this);
+            }
+        }
+    }
     
     public Set<String> getComponentNames() {
         return componentDefinitionRegistry.getComponentDefinitionNames();
@@ -455,7 +517,7 @@
     protected ComponentDefinitionRegistryImpl getComponentDefinitionRegistry() {
         return componentDefinitionRegistry;
     }
-    
+        
     public BundleContext getBundleContext() {
         return bundleContext;
     }
@@ -466,7 +528,8 @@
         }
         handlers.removeListener(this);
         sender.sendDestroying(this);
-        unregisterAllServices();        
+        unregisterAllServices();  
+        unregisterTriggerServices();
         destroyComponents();
         // TODO: stop all reference / collections
         System.out.println("Module context destroyed: " + this.bundleContext);

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintObjectRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintObjectRecipe.java?rev=771173&r1=771172&r2=771173&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintObjectRecipe.java
(original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/BlueprintObjectRecipe.java
Mon May  4 04:48:58 2009
@@ -197,18 +197,7 @@
             throw new ConstructionException("Unable to load type class " + typeName);
         }
     }
-    
-    private Object convert(Object source, Class type) throws ConstructionException {
-        if (type != null && blueprintContext != null) {
-            try {
-                source = blueprintContext.getConversionService().convert(source, type);
-            } catch (Exception e) {
-                throw new ConstructionException("Failed to convert", e);
-            }            
-        }
-        return source;
-    }
-    
+        
     private List<Object> getFinalArguments(ArgumentsMatch match, boolean refAllowed)
throws ConstructionException {
         List<Object> arguments = match.getArguments();
         Class[] parameterTypes = match.getParameterTypes();

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceRegistrationProxy.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceRegistrationProxy.java?rev=771173&r1=771172&r2=771173&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceRegistrationProxy.java
(original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceRegistrationProxy.java
Mon May  4 04:48:58 2009
@@ -31,7 +31,6 @@
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.blueprint.context.BlueprintContext;
 import org.osgi.service.blueprint.reflect.RefMetadata;
 import org.osgi.service.blueprint.reflect.RegistrationListener;
 import org.osgi.service.blueprint.reflect.ServiceMetadata;
@@ -45,7 +44,7 @@
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ServiceRegistrationProxy.class);
 
-    private BlueprintContext blueprintContext;
+    private BlueprintContextImpl blueprintContext;
     private Object service;
     private Map serviceProperties;
     private List<Listener> listeners;
@@ -71,27 +70,14 @@
             return;
         }
                 
-        Class serviceClass = service.getClass();
-        if (service instanceof BundleScopeServiceFactory) {
-            serviceClass = ((BundleScopeServiceFactory) service).getServiceClass();
-        }
-        Set<String> classes;
-        switch (metadata.getAutoExportMode()) {
-            case ServiceMetadata.AUTO_EXPORT_INTERFACES:
-                classes = ReflectionUtils.getImplementedInterfaces(new HashSet<String>(),
serviceClass);
-                break;
-            case ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY:
-                classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), serviceClass);
-                break;
-            case ServiceMetadata.AUTO_EXPORT_ALL_CLASSES:
-                classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), serviceClass);
-                classes = ReflectionUtils.getImplementedInterfaces(classes, serviceClass);
-                break;
-            default:
-                classes = new HashSet<String>(metadata.getInterfaceNames());
-                break;
+        TriggerService triggerService = blueprintContext.removeTriggerService(metadata);
+        if (triggerService != null) {
+            LOGGER.debug("Trigger service found");
+            triggerService.setService(service);
+            registration = triggerService.getRegistration();   
+            return;
         }
-                
+                        
         Hashtable props = new Hashtable();
         if (serviceProperties != null) {
             props.putAll(serviceProperties);
@@ -101,8 +87,8 @@
         if (componentName != null) {
             props.put(BlueprintConstants.COMPONENT_NAME_PROPERTY, componentName);
         }
-        String[] classesArray = classes.toArray(new String[classes.size()]);
-        registration = blueprintContext.getBundleContext().registerService(classesArray,
service, props);
+        String[] classes = getClasses();
+        registration = blueprintContext.getBundleContext().registerService(classes, service,
props);
         registrationProperties = props;
         
         LOGGER.debug("Service {} registered with interfaces {}", service, classes);
@@ -123,6 +109,31 @@
         }
     }
     
+    private String[] getClasses() {
+        Class serviceClass = service.getClass();
+        if (service instanceof BundleScopeServiceFactory) {
+            serviceClass = ((BundleScopeServiceFactory) service).getServiceClass();
+        }
+        Set<String> classes;
+        switch (metadata.getAutoExportMode()) {
+            case ServiceMetadata.AUTO_EXPORT_INTERFACES:
+                classes = ReflectionUtils.getImplementedInterfaces(new HashSet<String>(),
serviceClass);
+                break;
+            case ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY:
+                classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), serviceClass);
+                break;
+            case ServiceMetadata.AUTO_EXPORT_ALL_CLASSES:
+                classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), serviceClass);
+                classes = ReflectionUtils.getImplementedInterfaces(classes, serviceClass);
+                break;
+            default:
+                classes = new HashSet<String>(metadata.getInterfaceNames());
+                break;
+        }
+        String[] classesArray = classes.toArray(new String[classes.size()]);
+        return classesArray;
+    }
+    
     public String toString() {
         return service + " " + serviceProperties + " " + listeners;
     }

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/TriggerService.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/TriggerService.java?rev=771173&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/TriggerService.java
(added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/TriggerService.java
Mon May  4 04:48:58 2009
@@ -0,0 +1,139 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.geronimo.blueprint.context;
+
+import java.util.Hashtable;
+import java.util.List;
+
+import org.apache.geronimo.blueprint.BlueprintConstants;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.blueprint.reflect.RefMetadata;
+import org.osgi.service.blueprint.reflect.ServiceMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** 
+ * TODO: javadoc
+ */
+public class TriggerService implements ServiceFactory {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(TriggerService.class);
+    
+    private ServiceMetadata metadata;
+    private BlueprintContextImpl blueprintContext;  
+    private ServiceRegistration registration;
+    
+    private Object service;
+    
+    public TriggerService(ServiceMetadata metadata, BlueprintContextImpl blueprintContext)
{
+        this.metadata = metadata;
+        this.blueprintContext = blueprintContext;
+    }
+    
+    public synchronized void register() {
+        if (registration != null) {
+            return;
+        }
+        
+        Hashtable props = new Hashtable();
+        // TODO: handle service properties?
+        props.put(Constants.SERVICE_RANKING, metadata.getRanking());
+        String componentName = getComponentName();
+        if (componentName != null) {
+            props.put(BlueprintConstants.COMPONENT_NAME_PROPERTY, componentName);
+        }
+        String[] classes = getClasses();
+        registration = blueprintContext.getBundleContext().registerService(classes, this,
props);
+        
+        LOGGER.debug("Trigger service {} registered with interfaces {}", this, classes);
+    }
+    
+    private String getComponentName() {
+        if (metadata.getServiceComponent() instanceof RefMetadata) {
+            RefMetadata ref = (RefMetadata) metadata.getServiceComponent();
+            return ref.getComponentId();
+        } else {
+            return null;
+        }
+    }
+    
+    private String[] getClasses() {
+        List<String> interfaces = metadata.getInterfaceNames();
+        return interfaces.toArray(new String[interfaces.size()]);
+    }
+    
+    public synchronized void unregister() {   
+        if (registration != null) {
+            notifyAll();
+            registration.unregister();
+            registration = null;
+        }
+    }
+    
+    public Object getService(Bundle bundle, ServiceRegistration registration) {
+        LOGGER.debug("Service requested on trigger service. Requesting bundle start");
+        
+        try {
+            blueprintContext.forceActivation(true);
+        } catch (BundleException e) {
+            LOGGER.debug("Bundle activation failed", e);
+            // TODO: throw some exception or return null?
+            return null;
+        }
+        
+        waitForService();
+        
+        if (service instanceof ServiceFactory) {
+            return ((ServiceFactory) service).getService(bundle, registration);
+        } else {
+            return service;
+        }
+    }
+
+    public void ungetService(Bundle bundle, ServiceRegistration registration, Object service)
{
+        if (service instanceof ServiceFactory) {
+            ((ServiceFactory) service).ungetService(bundle, registration, service);
+        }
+    }  
+    
+    public ServiceRegistration getRegistration() {
+        return registration;
+    }
+    
+    public synchronized void setService(Object service) {
+        LOGGER.debug("Updated service object: {}", service);
+        this.service = service;
+        notifyAll();
+    }
+    
+    private synchronized void waitForService() {
+        try {
+            while(service == null) {
+                wait();
+            }
+        } catch (InterruptedException e) {
+            // break out
+        }
+    }
+    
+}

Propchange: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/TriggerService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/TriggerService.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/TriggerService.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/TestBlueprintContext.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/TestBlueprintContext.java?rev=771173&r1=771172&r2=771173&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/TestBlueprintContext.java
(original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/TestBlueprintContext.java
Mon May  4 04:48:58 2009
@@ -26,7 +26,7 @@
     private ComponentDefinitionRegistryImpl registry;
     
     public TestBlueprintContext(ComponentDefinitionRegistryImpl registry) {
-        super(new TestBundleContext(), null, null, null, null);
+        super(new TestBundleContext(), null, null, null, null, false);
         this.registry = registry;
     }
 



Mime
View raw message