geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gno...@apache.org
Subject svn commit: r776998 - in /geronimo/sandbox/blueprint: ./ blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/
Date Thu, 21 May 2009 07:53:05 GMT
Author: gnodet
Date: Thu May 21 07:53:05 2009
New Revision: 776998

URL: http://svn.apache.org/viewvc?rev=776998&view=rev
Log:
Implement trigger services for all services, allowing lazy creation of services (disabled
for now as there are a few problems atm)

Added:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceExportRecipe.java
Modified:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintObjectRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BundleScopeServiceFactory.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RecipeBuilder.java
    geronimo/sandbox/blueprint/pom.xml

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java?rev=776998&r1=776997&r2=776998&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java
(original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintContainerImpl.java
Thu May 21 07:53:05 2009
@@ -94,6 +94,10 @@
  */
 public class BlueprintContainerImpl implements ExtendedBlueprintContainer, NamespaceHandlerRegistry.Listener,
Runnable, SatisfiableRecipe.SatisfactionListener {
 
+    public static final boolean BEHAVIOR_TCK_INJECTION = true;
+    public static final boolean BEHAVIOR_NO_GRACE_PERIOD = false;
+    public static final boolean BEHAVIOR_ENHANCED_LAZY_ACTIVATION = false;
+
     private static final Logger LOGGER = LoggerFactory.getLogger(BlueprintContainerImpl.class);
 
     private enum State {
@@ -172,17 +176,21 @@
         Dictionary headers = bundle.getHeaders();
         String symbolicName = (String)headers.get(Constants.BUNDLE_SYMBOLICNAME);
         List<PathElement> paths = HeaderParser.parseHeader(symbolicName);
-        
-        String timeoutDirective = paths.get(0).getDirective(BlueprintConstants.TIMEOUT_DIRECTIVE);
       
-        if (timeoutDirective != null) {
-            LOGGER.debug("Timeout directive: " + timeoutDirective);
-            timeout = Integer.parseInt(timeoutDirective);
-        }
-        
-        String waitForDependenciesDirective = paths.get(0).getDirective(BlueprintConstants.WAIT_FOR_DEPENDENCIES_DIRECTIVE);
-        if (waitForDependenciesDirective != null) {
-            LOGGER.debug("Wait-for-dependencies directive: " + waitForDependenciesDirective);
-            waitForDependencies = Boolean.parseBoolean(waitForDependenciesDirective);
+
+        if (BEHAVIOR_NO_GRACE_PERIOD) {
+            waitForDependencies = false;
+        } else {
+            String timeoutDirective = paths.get(0).getDirective(BlueprintConstants.TIMEOUT_DIRECTIVE);
+            if (timeoutDirective != null) {
+                LOGGER.debug("Timeout directive: " + timeoutDirective);
+                timeout = Integer.parseInt(timeoutDirective);
+            }
+
+            String waitForDependenciesDirective = paths.get(0).getDirective(BlueprintConstants.WAIT_FOR_DEPENDENCIES_DIRECTIVE);
+            if (waitForDependenciesDirective != null) {
+                LOGGER.debug("Wait-for-dependencies directive: " + waitForDependenciesDirective);
+                waitForDependencies = Boolean.parseBoolean(waitForDependenciesDirective);
+            }
         }
         
         // TODO: add support for custom directive to disable schema validation?
@@ -300,11 +308,15 @@
                         //       the lazy activation should be a best effot and the lazy
creation of services should be
                         //       done in all cases
                         //       Not sure about listeners
-                        if (lazyActivation) {
-                            registerTriggerServices();
-                            state = State.WaitForTrigger;                            
-                        } else {
+                        if (BEHAVIOR_ENHANCED_LAZY_ACTIVATION) {
                             state = State.Create;
+                        } else {
+                            if (lazyActivation) {
+                                registerTriggerServices();
+                                state = State.WaitForTrigger;
+                            } else {
+                                state = State.Create;
+                            }
                         }
                         break;
                     case WaitForTrigger:
@@ -523,13 +535,24 @@
                             break;
                         }
                     }
-                    ServiceRegistrationProxy reg = (ServiceRegistrationProxy) getComponent(name);
-                    if (satisfied && !reg.isRegistered()) {
-                        LOGGER.debug("Registering service {} due to satisfied references",
name);
-                        reg.register();
-                    } else if (!satisfied && reg.isRegistered()) {
-                        LOGGER.debug("Unregistering service {} due to unsatisfied references",
name);
-                        reg.unregister();
+                    if (BEHAVIOR_ENHANCED_LAZY_ACTIVATION) {
+                        ServiceExportRecipe reg = (ServiceExportRecipe) getComponent(name);
+                        if (satisfied && !reg.isRegistered()) {
+                            LOGGER.debug("Registering service {} due to satisfied references",
name);
+                            reg.register();
+                        } else if (!satisfied && reg.isRegistered()) {
+                            LOGGER.debug("Unregistering service {} due to unsatisfied references",
name);
+                            reg.unregister();
+                        }
+                    } else {
+                        ServiceRegistrationProxy reg = (ServiceRegistrationProxy) getComponent(name);
+                        if (satisfied && !reg.isRegistered()) {
+                            LOGGER.debug("Registering service {} due to satisfied references",
name);
+                            reg.register();
+                        } else if (!satisfied && reg.isRegistered()) {
+                            LOGGER.debug("Unregistering service {} due to unsatisfied references",
name);
+                            reg.unregister();
+                        }
                     }
                 }
             }
@@ -547,7 +570,27 @@
                     components.add(name);
                 }
             } else {
-                components.add(name);
+                if (BEHAVIOR_ENHANCED_LAZY_ACTIVATION) {
+                    if (component instanceof ServiceMetadata) {
+                        List<SatisfiableRecipe> dependencies = getSatisfiableDependenciesMap().get(name);
+                        boolean satisfied = true;
+                        if (dependencies != null) {
+                            for (SatisfiableRecipe recipe : dependencies) {
+                                if (!recipe.isSatisfied()) {
+                                    satisfied = false;
+                                    break;
+                                }
+                            }
+                        }
+                        if (satisfied) {
+                            Recipe r = ((DefaultRepository) instantiator.getRepository()).getRecipe(name);
+                            ((ServiceExportRecipe) r).register();
+                        }
+                        components.add(name);
+                    }
+                } else {
+                    components.add(name);
+                }
             }
         }
         LOGGER.debug("Instantiating components: {}", components);

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintObjectRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintObjectRecipe.java?rev=776998&r1=776997&r2=776998&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintObjectRecipe.java
(original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintObjectRecipe.java
Thu May 21 07:53:05 2009
@@ -281,8 +281,6 @@
         return instance;
     }
 
-    public static final boolean TCK_COMPLIANCE = true;
-
     private Map<Method, List<Object>> findMatchingMethods(Class type, String
name, boolean instance, List<Object> args, List<Class> types) {
         Map<Method, List<Object>> matches = new HashMap<Method, List<Object>>();
         // Get constructors
@@ -299,7 +297,7 @@
             }
         }
         // Find a direct match with no conversion
-        if (TCK_COMPLIANCE && matches.size() != 1) {
+        if (BlueprintContainerImpl.BEHAVIOR_TCK_INJECTION && matches.size() != 1)
{
             Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
             int bestExactMatch = -1;
             for (Method mth : methods) {
@@ -399,7 +397,7 @@
             }
         }
         // Find a direct match with no conversion
-        if (TCK_COMPLIANCE && matches.size() != 1) {
+        if (BlueprintContainerImpl.BEHAVIOR_TCK_INJECTION && matches.size() != 1)
{
             Map<Constructor, List<Object>> nmatches = new HashMap<Constructor,
List<Object>>();
             int bestExactMatch = -1;
             for (Constructor cns : constructors) {

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BundleScopeServiceFactory.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BundleScopeServiceFactory.java?rev=776998&r1=776997&r2=776998&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BundleScopeServiceFactory.java
(original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BundleScopeServiceFactory.java
Thu May 21 07:53:05 2009
@@ -30,12 +30,16 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /** 
  * TODO: javadoc
  */
 public class BundleScopeServiceFactory implements ServiceFactory {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(BundleScopeServiceFactory.class);
+
     private BlueprintContainerImpl blueprintContainer;
     private BlueprintObjectRecipe serviceRecipe;
     private Map<Bundle, Entry> instanceMap = Collections.synchronizedMap(new HashMap<Bundle,
Entry>());
@@ -51,7 +55,7 @@
             entry = instanceMap.get(bundle);
             if (entry == null) {
                 entry = new Entry(createInstance());
-                System.out.println("Created service instance for bundle: " + bundle + " "
+ entry.getServiceInstance().hashCode());
+                LOGGER.debug("Created service instance for bundle: " + bundle + " " + entry.getServiceInstance().hashCode());
                 instanceMap.put(bundle, entry);                
             }       
             entry.addServiceRegistration(registration);
@@ -66,7 +70,7 @@
                 entry.removeServiceRegistration(registration);
                 if (!entry.hasServiceRegistrations()) {
                     destroyInstance(entry.getServiceInstance());
-                    System.out.println("Destroyed service instance for bundle: " + bundle);
+                    LOGGER.debug("Destroyed service instance for bundle: " + bundle);
                     instanceMap.remove(bundle);
                 }
             }

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RecipeBuilder.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RecipeBuilder.java?rev=776998&r1=776997&r2=776998&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RecipeBuilder.java
(original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/RecipeBuilder.java
Thu May 21 07:53:05 2009
@@ -156,33 +156,51 @@
         return recipe;
     }
 
-    private BlueprintObjectRecipe createServiceRecipe(ServiceMetadata serviceExport) throws
Exception {
-        BlueprintObjectRecipe recipe = new BlueprintObjectRecipe(blueprintContainer, ServiceRegistrationProxy.class);
-        recipe.setName(getName(serviceExport.getId()));
-        recipe.setExplicitDependencies(serviceExport.getExplicitDependencies());
-        recipe.setInitMethod("init");
-        recipe.setAllowPartial(true);
-        recipe.setProperty("blueprintContainer", blueprintContainer);
-        BeanMetadata exportedComponent = getLocalServiceComponent(serviceExport.getServiceComponent());
-        if (exportedComponent != null && BeanMetadata.SCOPE_BUNDLE.equals(exportedComponent.getScope()))
{
-            BlueprintObjectRecipe exportedComponentRecipe = createBeanRecipe(exportedComponent);
-            recipe.setProperty("service", new BundleScopeServiceFactory(blueprintContainer,
exportedComponentRecipe));
-        } else {
-            recipe.setProperty("service", getValue(serviceExport.getServiceComponent(), null));
-        }
-        recipe.setProperty("metadata", serviceExport);
-        Recipe propertiesRecipe = getServicePropertiesRecipe(serviceExport);
-        if (propertiesRecipe != null) {
-            recipe.setProperty("serviceProperties", propertiesRecipe);
-        }
-        if (serviceExport.getRegistrationListeners() != null) {
+    private Recipe createServiceRecipe(ServiceMetadata serviceExport) throws Exception {
+        if (BlueprintContainerImpl.BEHAVIOR_ENHANCED_LAZY_ACTIVATION) {
             CollectionRecipe listenersRecipe = new CollectionRecipe(ArrayList.class);
-            for (RegistrationListener listener : serviceExport.getRegistrationListeners())
{
-                listenersRecipe.add(createRecipe(listener));
+            if (serviceExport.getRegistrationListeners() != null) {
+                for (RegistrationListener listener : serviceExport.getRegistrationListeners())
{
+                    listenersRecipe.add(createRecipe(listener));
+                }
+            }
+            listenersRecipe.setName(getName(null));
+            ServiceExportRecipe recipe = new ServiceExportRecipe(
+                    blueprintContainer,
+                    serviceExport,
+                    getValue(serviceExport.getServiceComponent(), null),
+                    listenersRecipe,
+                    (MapRecipe) getServicePropertiesRecipe(serviceExport));
+            recipe.setName(getName(serviceExport.getId()));
+            return recipe;
+        } else {
+            BlueprintObjectRecipe recipe = new BlueprintObjectRecipe(blueprintContainer,
ServiceRegistrationProxy.class);
+            recipe.setName(getName(serviceExport.getId()));
+            recipe.setExplicitDependencies(serviceExport.getExplicitDependencies());
+            recipe.setInitMethod("init");
+            recipe.setAllowPartial(true);
+            recipe.setProperty("blueprintContainer", blueprintContainer);
+            BeanMetadata exportedComponent = getLocalServiceComponent(serviceExport.getServiceComponent());
+            if (exportedComponent != null && BeanMetadata.SCOPE_BUNDLE.equals(exportedComponent.getScope()))
{
+                BlueprintObjectRecipe exportedComponentRecipe = createBeanRecipe(exportedComponent);
+                recipe.setProperty("service", new BundleScopeServiceFactory(blueprintContainer,
exportedComponentRecipe));
+            } else {
+                recipe.setProperty("service", getValue(serviceExport.getServiceComponent(),
null));
+            }
+            recipe.setProperty("metadata", serviceExport);
+            Recipe propertiesRecipe = getServicePropertiesRecipe(serviceExport);
+            if (propertiesRecipe != null) {
+                recipe.setProperty("serviceProperties", propertiesRecipe);
+            }
+            if (serviceExport.getRegistrationListeners() != null) {
+                CollectionRecipe listenersRecipe = new CollectionRecipe(ArrayList.class);
+                for (RegistrationListener listener : serviceExport.getRegistrationListeners())
{
+                    listenersRecipe.add(createRecipe(listener));
+                }
+                recipe.setProperty("listeners", listenersRecipe);
             }
-            recipe.setProperty("listeners", listenersRecipe);
+            return recipe;
         }
-        return recipe;
     }
 
     protected Recipe getServicePropertiesRecipe(ServiceMetadata metadata) throws Exception
{
@@ -240,16 +258,26 @@
     }
 
     private Recipe createRecipe(RegistrationListener listener) throws Exception {
-        BlueprintObjectRecipe recipe = new BlueprintObjectRecipe(blueprintContainer, ServiceRegistrationProxy.Listener.class);
-        recipe.setProperty("listener", getValue(listener.getListenerComponent(), null));
-        recipe.setProperty("metadata", listener);
-        return recipe;
+        if (BlueprintContainerImpl.BEHAVIOR_ENHANCED_LAZY_ACTIVATION) {
+            BlueprintObjectRecipe recipe = new BlueprintObjectRecipe(blueprintContainer,
ServiceExportRecipe.Listener.class);
+            recipe.setProperty("listener", getValue(listener.getListenerComponent(), null));
+            recipe.setProperty("metadata", listener);
+            recipe.setName(getName(null));
+            return recipe;
+        } else {
+            BlueprintObjectRecipe recipe = new BlueprintObjectRecipe(blueprintContainer,
ServiceRegistrationProxy.Listener.class);
+            recipe.setProperty("listener", getValue(listener.getListenerComponent(), null));
+            recipe.setProperty("metadata", listener);
+            recipe.setName(getName(null));
+            return recipe;
+        }
     }
 
     private Recipe createRecipe(Listener listener) throws Exception {
         BlueprintObjectRecipe recipe = new BlueprintObjectRecipe(blueprintContainer, AbstractServiceReferenceRecipe.Listener.class);
         recipe.setProperty("listener", getValue(listener.getListenerComponent(), null));
         recipe.setProperty("metadata", listener);
+        recipe.setName(getName(null));
         return recipe;
     }
 
@@ -277,11 +305,15 @@
             ValueMetadata stringValue = (ValueMetadata) v;
             Object type = stringValue.getTypeName();
             type = (type == null) ? groupingType : type;
-            return new ValueRecipe(stringValue, type);
+            ValueRecipe vr = new ValueRecipe(stringValue, type);
+            vr.setName(getName(null));
+            return vr;
         } else if (v instanceof RefMetadata) {
             // TODO: make it work with property-placeholders?
             String componentName = ((RefMetadata) v).getComponentId();
-            return new ReferenceRecipe(componentName);
+            ReferenceRecipe rr = new ReferenceRecipe(componentName);
+            rr.setName(getName(null));
+            return rr;
         } else if (v instanceof CollectionMetadata) {
             CollectionMetadata collectionMetadata = (CollectionMetadata) v;
             Class cl = collectionMetadata.getCollectionClass();
@@ -291,12 +323,14 @@
                 for (Metadata lv : collectionMetadata.getValues()) {
                     ar.add(getValue(lv, type));
                 }
+                ar.setName(getName(null));
                 return ar;
             } else {
                 CollectionRecipe cr = new CollectionRecipe(cl);
                 for (Metadata lv : collectionMetadata.getValues()) {
                     cr.add(getValue(lv, type));
                 }
+                cr.setName(getName(null));
                 return cr;
             }
         } else if (v instanceof MapMetadata) {
@@ -309,6 +343,7 @@
                 Recipe val = getValue(entry.getValue(), valueType);
                 mr.put(key, val);
             }
+            mr.setName(getName(null));
             return mr;
         } else if (v instanceof PropsMetadata) {
             PropsMetadata mapValue = (PropsMetadata) v;
@@ -318,11 +353,14 @@
                 Recipe val = getValue(entry.getValue(), String.class);
                 mr.put(key, val);
             }
+            mr.setName(getName(null));
             return mr;
         } else if (v instanceof IdRefMetadata) {
             // TODO: make it work with property-placeholders?
             String componentName = ((IdRefMetadata) v).getComponentId();
-            return new ReferenceNameRecipe(componentName);
+            ReferenceNameRecipe rnr = new ReferenceNameRecipe(componentName);
+            rnr.setName(getName(null));
+            return rnr;
         } else {
             throw new IllegalStateException("Unsupported value: " + v.getClass().getName());
         }

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceExportRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceExportRecipe.java?rev=776998&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceExportRecipe.java
(added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/ServiceExportRecipe.java
Thu May 21 07:53:05 2009
@@ -0,0 +1,397 @@
+package org.apache.geronimo.blueprint.container;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.geronimo.blueprint.BlueprintConstants;
+import org.apache.geronimo.blueprint.di.AbstractRecipe;
+import org.apache.geronimo.blueprint.di.CollectionRecipe;
+import org.apache.geronimo.blueprint.di.ConstructionException;
+import org.apache.geronimo.blueprint.di.DefaultRepository;
+import org.apache.geronimo.blueprint.di.MapRecipe;
+import org.apache.geronimo.blueprint.di.ObjectGraph;
+import org.apache.geronimo.blueprint.di.Recipe;
+import org.apache.geronimo.blueprint.di.ReferenceRecipe;
+import org.apache.geronimo.blueprint.di.Repository;
+import org.apache.geronimo.blueprint.di.ExecutionContext;
+import org.apache.geronimo.blueprint.di.DefaultExecutionContext;
+import org.apache.geronimo.blueprint.utils.ReflectionUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.blueprint.reflect.BeanMetadata;
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
+import org.osgi.service.blueprint.reflect.Metadata;
+import org.osgi.service.blueprint.reflect.RefMetadata;
+import org.osgi.service.blueprint.reflect.RegistrationListener;
+import org.osgi.service.blueprint.reflect.ServiceMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A <code>Recipe</code> to export services into the OSGi registry.
+ *
+ * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
+ * @version $Rev: 776360 $, $Date: 2009-05-19 17:40:47 +0200 (Tue, 19 May 2009) $
+ */
+public class ServiceExportRecipe extends AbstractRecipe implements ServiceRegistration {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceRegistrationProxy.class);
+
+    private BlueprintContainerImpl blueprintContainer;
+    private ServiceMetadata metadata;
+    private Recipe serviceRecipe;
+    private CollectionRecipe listenersRecipe;
+    private MapRecipe propertiesRecipe;
+
+    private Map properties;
+    private ServiceRegistration registration;
+    private Map registrationProperties;
+    private List<Listener> listeners;
+    private Map<Bundle, Entry> instanceMap = Collections.synchronizedMap(new HashMap<Bundle,
Entry>());
+    private Object service;
+    private boolean bundleScope;
+
+    public ServiceExportRecipe(BlueprintContainerImpl blueprintContainer,
+                               ServiceMetadata metadata,
+                               Recipe serviceRecipe,
+                               CollectionRecipe listenersRecipe,
+                               MapRecipe propertiesRecipe) {
+        this.blueprintContainer = blueprintContainer;
+        this.metadata = metadata;
+        this.serviceRecipe = serviceRecipe;
+        this.listenersRecipe = listenersRecipe;
+        this.propertiesRecipe = propertiesRecipe;
+    }
+
+    protected Object internalCreate(boolean lazyRefAllowed) throws ConstructionException
{
+        return this;
+    }
+
+    public synchronized void register() {
+        if (registration != null) {
+            return;
+        }
+        Hashtable props = new Hashtable();
+        if (properties == null) {
+            properties = (Map) createSimpleRecipe(propertiesRecipe);
+        }
+        props.putAll(properties);
+        props.put(Constants.SERVICE_RANKING, metadata.getRanking());
+        String componentName = getComponentName();
+        if (componentName != null) {
+            props.put(BlueprintConstants.COMPONENT_NAME_PROPERTY, componentName);
+        }
+        Set<String> classes = getClasses();
+        String[] classArray = classes.toArray(new String[classes.size()]);
+        registration = blueprintContainer.getBundleContext().registerService(classArray,
new TriggerServiceFactory(), props);
+        registrationProperties = props;
+
+        LOGGER.debug("Trigger service {} registered with interfaces {} and properties {}",
+                     new Object[] { this, classes, props });
+    }
+
+    public synchronized boolean isRegistered() {
+        return registration != null;
+    }
+
+    public synchronized ServiceReference getReference() {
+        if (registration == null) {
+            throw new IllegalStateException();
+        } else {
+            return registration.getReference();
+        }
+    }
+
+    public synchronized void setProperties(Dictionary props) {
+        if (registration == null) {
+            throw new IllegalStateException();
+        } else {
+            registration.setProperties(props);
+            // TODO: set serviceProperties? convert somehow? should listeners be notified
of this?
+        }
+    }
+
+
+    public synchronized void unregister() {
+        if (registration != null) {
+            // TODO: shouldn't listeners be called before unregistering the service?
+            registration.unregister();
+            if (listeners != null) {
+                for (Listener listener : listeners) {
+                    listener.unregister(this);
+                }
+            }
+            LOGGER.debug("Service {} unregistered", service);
+            registration = null;
+        }
+    }
+
+    public Object getService() {
+        return getService(blueprintContainer.getBundleContext().getBundle(), null);
+    }
+
+    public Object getService(Bundle bundle, ServiceRegistration registration) {
+        // Create initial service
+        if (this.service == null) {
+            synchronized (this) {
+                if (this.service == null) {
+                    bundleScope = isBundleScope(metadata.getServiceComponent());
+                    this.service = createInstance(false);
+                    // When the service is first requested, we need to create listeners and
call them
+                    if (listeners == null) {
+                        if (listenersRecipe != null) {
+                            listeners = (List) createSimpleRecipe(listenersRecipe);
+                        } else {
+                            listeners = Collections.emptyList();
+                        }
+                        for (Listener listener : listeners) {
+                            listener.register(this);
+                        }
+                    }
+                }
+            }
+        }
+        Object service = this.service;
+        if (service instanceof ServiceFactory) {
+            service = ((ServiceFactory) service).getService(bundle, registration);
+        } else if (bundleScope) {
+            Entry entry;
+            synchronized(bundle) {
+                entry = instanceMap.get(bundle);
+                if (entry == null) {
+                    entry = new Entry(createInstance(true));
+                    LOGGER.debug("Created service instance for bundle: " + bundle + " " +
entry.getServiceInstance().hashCode());
+                    instanceMap.put(bundle, entry);
+                }
+                entry.addServiceRegistration(registration);
+            }
+            service = entry.getServiceInstance();
+        }
+        return service;
+    }
+
+    public void ungetService(Bundle bundle, ServiceRegistration registration, Object service)
{
+        if (bundleScope) {
+            synchronized(bundle) {
+                Entry entry = instanceMap.get(bundle);
+                if (entry != null) {
+                    entry.removeServiceRegistration(registration);
+                    if (!entry.hasServiceRegistrations()) {
+                        destroyInstance(entry.getServiceInstance());
+                        LOGGER.debug("Destroyed service instance for bundle: " + bundle);
+                        instanceMap.remove(bundle);
+                    }
+                }
+            }
+        }
+    }
+
+    private Set<String> getClasses() {
+        Set<String> classes;
+        switch (metadata.getAutoExportMode()) {
+            case ServiceMetadata.AUTO_EXPORT_INTERFACES:
+                classes = ReflectionUtils.getImplementedInterfaces(new HashSet<String>(),
getService().getClass());
+                break;
+            case ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY:
+                classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), getService().getClass());
+                break;
+            case ServiceMetadata.AUTO_EXPORT_ALL_CLASSES:
+                classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), getService().getClass());
+                classes = ReflectionUtils.getImplementedInterfaces(classes, getService().getClass());
+                break;
+            default:
+                classes = new HashSet<String>(metadata.getInterfaceNames());
+                break;
+        }
+        return classes;
+    }
+
+    private Object createInstance(boolean scoped) {
+        if (scoped) {
+            Recipe recipe = serviceRecipe;
+            Repository objectRepository = blueprintContainer.getRepository();
+            if (recipe instanceof ReferenceRecipe) {
+                recipe = (Recipe) objectRepository.get(((ReferenceRecipe) recipe).getReferenceName());
+            }
+            DefaultRepository repository = new DefaultRepository((DefaultRepository) objectRepository);
+            repository.set(recipe.getName(), recipe);
+            BlueprintObjectInstantiator graph = new BlueprintObjectInstantiator(blueprintContainer,
repository);
+            return graph.create(recipe.getName());
+        } else {
+            return createSimpleRecipe(serviceRecipe);
+        }
+    }
+
+    private Object createSimpleRecipe(Recipe recipe) {
+        String name = recipe.getName();
+        DefaultRepository repo = (DefaultRepository) blueprintContainer.getRepository();
+        if (repo.getRecipe(name) == null) {
+            repo.putRecipe(name, recipe);
+        }
+        BlueprintObjectInstantiator graph = new BlueprintObjectInstantiator(blueprintContainer,
repo);
+        return graph.create(name);
+    }
+
+    private void destroyInstance(Object instance) {
+        Recipe recipe = serviceRecipe;
+        Repository objectRepository = blueprintContainer.getRepository();
+        if (recipe instanceof ReferenceRecipe) {
+            recipe = (Recipe) objectRepository.get(((ReferenceRecipe) recipe).getReferenceName());
+        }
+        ((BlueprintObjectRecipe) recipe).destroyInstance(instance);
+    }
+
+    private boolean isBundleScope(Metadata value) {
+        ComponentMetadata metadata = null;
+        if (value instanceof RefMetadata) {
+            RefMetadata ref = (RefMetadata) value;
+            metadata = blueprintContainer.getComponentDefinitionRegistry().getComponentDefinition(ref.getComponentId());
+        } else if (value instanceof ComponentMetadata) {
+            metadata = (ComponentMetadata) value;
+        }
+        if (metadata instanceof BeanMetadata) {
+            BeanMetadata bean = (BeanMetadata) metadata;
+            Class clazz = bean.getRuntimeClass();
+            if (clazz == null) {
+                boolean isNewContext = !ExecutionContext.isContextSet();
+                if (isNewContext) {
+                    ExecutionContext.setContext(new DefaultExecutionContext(blueprintContainer,
blueprintContainer.getRepository()));
+                }
+                try {
+                    clazz = loadClass(bean.getClassName());
+                } finally {
+                    if (isNewContext) {
+                        ExecutionContext.setContext(null);
+                    }
+                }
+            }
+            if (ServiceFactory.class.isAssignableFrom(clazz)) {
+                return false;
+            } else {
+                return BeanMetadata.SCOPE_BUNDLE.equals(bean.getScope());
+            }
+        } else {
+            return false;
+        }
+    }
+
+    private String getComponentName() {
+        if (metadata.getServiceComponent() instanceof RefMetadata) {
+            RefMetadata ref = (RefMetadata) metadata.getServiceComponent();
+            return ref.getComponentId();
+        } else {
+            return null;
+        }
+    }
+
+    private class TriggerServiceFactory implements ServiceFactory {
+
+        public Object getService(Bundle bundle, ServiceRegistration registration) {
+            return ServiceExportRecipe.this.getService(bundle, registration);
+        }
+
+        public void ungetService(Bundle bundle, ServiceRegistration registration, Object
service) {
+            ServiceExportRecipe.this.ungetService(bundle, registration, service);
+        }
+
+    }
+
+    public static class Listener {
+
+        private Object listener;
+        private RegistrationListener metadata;
+
+        private List<Method> registerMethods;
+        private List<Method> unregisterMethods;
+        private boolean initialized = false;
+
+        public void setListener(Object listener) {
+            this.listener = listener;
+        }
+
+        public void setMetadata(RegistrationListener metadata) {
+            this.metadata = metadata;
+        }
+
+        public void register(ServiceExportRecipe recipe) {
+            init(recipe);
+            invokeMethod(registerMethods, recipe);
+        }
+
+        public void unregister(ServiceExportRecipe recipe) {
+            invokeMethod(unregisterMethods, recipe);
+        }
+
+        private synchronized void init(ServiceExportRecipe recipe) {
+            if (initialized) {
+                return;
+            }
+            Object service = recipe.getService();
+            Class[] paramTypes = new Class[] { service.getClass(), Map.class };
+            Class listenerClass = listener.getClass();
+
+            if (metadata.getRegistrationMethodName() != null) {
+                registerMethods = ReflectionUtils.findCompatibleMethods(listenerClass, metadata.getRegistrationMethodName(),
paramTypes);
+            }
+            if (metadata.getUnregistrationMethodName() != null) {
+                unregisterMethods = ReflectionUtils.findCompatibleMethods(listenerClass,
metadata.getUnregistrationMethodName(), paramTypes);
+            }
+            initialized = true;
+        }
+
+        private void invokeMethod(List<Method> methods, ServiceExportRecipe recipe)
{
+            if (methods == null || methods.isEmpty()) {
+                return;
+            }
+            Object service = recipe.getService();
+            Map properties = recipe.registrationProperties;
+            Object[] args = new Object[] { service, properties };
+            for (Method method : methods) {
+                try {
+                    method.invoke(listener, args);
+                } catch (Exception e) {
+                    LOGGER.info("Error calling listener method " + method, e);
+                }
+            }
+        }
+
+    }
+
+    private static class Entry {
+
+        private final Object serviceInstance;
+        private final Set<ServiceRegistration> registrations = new HashSet<ServiceRegistration>();
+
+        public Entry(Object serviceInstance) {
+            this.serviceInstance = serviceInstance;
+        }
+
+        public Object getServiceInstance() {
+            return this.serviceInstance;
+        }
+
+        public boolean hasServiceRegistrations() {
+            return !registrations.isEmpty();
+        }
+
+        public void addServiceRegistration(ServiceRegistration registration) {
+            registrations.add(registration);
+        }
+
+        public void removeServiceRegistration(ServiceRegistration registration) {
+            registrations.remove(registration);
+        }
+
+    }
+
+}

Modified: geronimo/sandbox/blueprint/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/pom.xml?rev=776998&r1=776997&r2=776998&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/pom.xml (original)
+++ geronimo/sandbox/blueprint/pom.xml Thu May 21 07:53:05 2009
@@ -136,7 +136,7 @@
             <dependency>
                 <groupId>org.ops4j.pax.url</groupId>
                 <artifactId>pax-url-mvn</artifactId>
-                <version>0.3.3</version>
+                <version>0.5.2</version>
             </dependency>
         </dependencies>
     </dependencyManagement>



Mime
View raw message