You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by gn...@apache.org on 2009/04/14 00:34:50 UTC

svn commit: r764641 - in /geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint: ./ context/ convert/ namespace/

Author: gnodet
Date: Mon Apr 13 22:34:49 2009
New Revision: 764641

URL: http://svn.apache.org/viewvc?rev=764641&view=rev
Log:
Import activator / conversion service from Jarek / Rick

Added:
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/Activator.java
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/ModuleContextEventSender.java
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/NamespaceHandlerRegistry.java
      - copied, changed from r764560, geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistry.java
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/DefaultModuleContextEventSender.java
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/WaitForDependencyException.java
Removed:
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistry.java
Modified:
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Instanciator.java
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/ModuleContextImpl.java
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Parser.java
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/convert/ConversionServiceImpl.java
    geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistryImpl.java

Added: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/Activator.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/Activator.java?rev=764641&view=auto
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/Activator.java (added)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/Activator.java Mon Apr 13 22:34:49 2009
@@ -0,0 +1,103 @@
+package org.apache.felix.blueprint;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.blueprint.context.DefaultModuleContextEventSender;
+import org.apache.felix.blueprint.context.ModuleContextImpl;
+import org.apache.felix.blueprint.namespace.NamespaceHandlerRegistryImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.SynchronousBundleListener;
+
+/**
+ * TODO: javadoc
+ *
+ * TODO: handle ModuleContextListener
+ */
+public class Activator implements BundleActivator, BundleListener {
+
+    private StopBundleListener stopBundleListener = new StopBundleListener();
+    private Map<Bundle, ModuleContextImpl> contextMap = new HashMap<Bundle, ModuleContextImpl>();
+    private ModuleContextEventSender sender;
+    private NamespaceHandlerRegistry handlers;
+
+    public void start(BundleContext context) {
+        System.out.println("Starting to listen for bundle events.");
+        context.addBundleListener(stopBundleListener);
+        context.addBundleListener(this);
+
+        sender = new DefaultModuleContextEventSender(context);
+        handlers = new NamespaceHandlerRegistryImpl(context);
+
+        Bundle[] bundles = context.getBundles();
+        for (Bundle b : bundles) {
+            if (b.getState() == Bundle.ACTIVE) {
+                checkBundle(b);
+            }
+        }
+    }
+
+
+    public void stop(BundleContext context) {
+        context.removeBundleListener(stopBundleListener);
+        context.removeBundleListener(this);
+        this.sender.destroy();
+        this.handlers.destroy();
+        System.out.println("Stopped listening for bundle events.");
+    }
+
+    public void bundleChanged(BundleEvent event) {
+        System.out.println("bundle changed:" + event.getBundle().getSymbolicName() + "  "+ event.getType());
+        if (event.getType() == BundleEvent.STARTED) {
+            checkBundle(event.getBundle());
+        }
+    }
+
+    private void destroyContext(Bundle bundle) {
+        ModuleContextImpl moduleContext = contextMap.remove(bundle);
+        if (moduleContext != null) {
+            moduleContext.destroy();
+        }
+    }
+
+    private void checkBundle(Bundle b) {
+        System.out.println("Checking: " + b.getSymbolicName());
+
+        List<URL> urls = new ArrayList<URL>();
+        Enumeration e = b.findEntries("OSGI-INF/blueprint", "*.xml", true);
+        if (e != null) {
+            while (e.hasMoreElements()) {
+                URL u = (URL) e.nextElement();
+                System.out.println("found xml config:" + u);
+                urls.add(u);
+            }
+        }
+        if (urls.size() > 0) {
+            ModuleContextImpl moduleContext = new ModuleContextImpl(b.getBundleContext(), sender, urls.toArray(new URL[urls.size()]));
+            contextMap.put(b, moduleContext);
+            moduleContext.create();
+        }
+
+        Dictionary d = b.getHeaders();
+        System.out.println(d.get("Bundle-Blueprint"));
+    }
+
+
+    private class StopBundleListener implements SynchronousBundleListener {
+        public void bundleChanged(BundleEvent event) {
+            if (event.getType() == BundleEvent.STOPPING) {
+                destroyContext(event.getBundle());
+            }
+        }
+    }
+
+}

Added: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/ModuleContextEventSender.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/ModuleContextEventSender.java?rev=764641&view=auto
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/ModuleContextEventSender.java (added)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/ModuleContextEventSender.java Mon Apr 13 22:34:49 2009
@@ -0,0 +1,26 @@
+package org.apache.felix.blueprint;
+
+import org.apache.felix.blueprint.context.ModuleContextImpl;
+import org.osgi.service.blueprint.context.ModuleContext;
+import org.osgi.service.blueprint.context.ModuleContextEventConstants;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: gnodet
+ * Date: Apr 13, 2009
+ * Time: 11:18:06 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public interface ModuleContextEventSender extends ModuleContextEventConstants {
+
+    void sendCreating(ModuleContext moduleContext);
+    void sendCreated(ModuleContext moduleContext);
+    void sendDestroying(ModuleContext moduleContext);
+    void sendDestroyed(ModuleContext moduleContext);
+    void sendWaiting(ModuleContext moduleContext, String[] serviceObjectClass, String serviceFilter);
+    void sendFailure(ModuleContext moduleContext, Throwable cause);
+    void sendFailure(ModuleContext moduleContext, Throwable cause, String[] serviceObjectClass, String serviceFilter);
+
+    void destroy();
+
+}

Copied: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/NamespaceHandlerRegistry.java (from r764560, geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistry.java)
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/NamespaceHandlerRegistry.java?p2=geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/NamespaceHandlerRegistry.java&p1=geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistry.java&r1=764560&r2=764641&rev=764641&view=diff
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistry.java (original)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/NamespaceHandlerRegistry.java Mon Apr 13 22:34:49 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.blueprint.namespace;
+package org.apache.felix.blueprint;
 
 import java.net.URI;
 
@@ -30,5 +30,19 @@
  */
 public interface NamespaceHandlerRegistry {
 
+    /**
+     * Retrieve the <code>NamespaceHandler</code> for the specified URI
+     *
+     * @param uri the namespace identifying the namespace handler
+     * @return the registered <code>NamespaceHandler</code> or <code>null</code> if none has been registered for the given namespace
+     */
     NamespaceHandler getNamespaceHandler(URI uri);
+
+    /**
+     * Add a callback to be run each time the list of namespace handlers changes
+     * @param runnable
+     */
+    void addCallback(Runnable runnable);
+
+    void destroy();
 }

Added: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/DefaultModuleContextEventSender.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/DefaultModuleContextEventSender.java?rev=764641&view=auto
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/DefaultModuleContextEventSender.java (added)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/DefaultModuleContextEventSender.java Mon Apr 13 22:34:49 2009
@@ -0,0 +1,94 @@
+package org.apache.felix.blueprint.context;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Bundle;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.Event;
+import org.osgi.service.blueprint.context.ModuleContextEventConstants;
+import org.osgi.service.blueprint.context.ModuleContext;
+import org.apache.felix.blueprint.ModuleContextEventSender;
+
+/**
+ * TODO: javadoc
+ */
+public class DefaultModuleContextEventSender implements ModuleContextEventSender {
+
+    private final ServiceTracker eventAdminServiceTracker;
+
+    public DefaultModuleContextEventSender(BundleContext bundleContext) {
+        this.eventAdminServiceTracker = new ServiceTracker(bundleContext, EventAdmin.class.getName(), null);
+        this.eventAdminServiceTracker.open();
+    }
+
+    public void sendCreating(ModuleContext moduleContext) {
+        sendEvent(moduleContext, TOPIC_CREATING, null, null, null);
+    }
+
+    public void sendCreated(ModuleContext moduleContext) {
+        sendEvent(moduleContext, TOPIC_CREATED, null, null, null);
+    }
+
+    public void sendDestroying(ModuleContext moduleContext) {
+        sendEvent(moduleContext, TOPIC_DESTROYING, null, null, null);
+    }
+
+    public void sendDestroyed(ModuleContext moduleContext) {
+        sendEvent(moduleContext, TOPIC_DESTROYED, null, null, null);
+    }
+
+    public void sendWaiting(ModuleContext moduleContext, String[] serviceObjectClass, String serviceFilter) {
+        sendEvent(moduleContext, TOPIC_WAITING, null, serviceObjectClass, serviceFilter);
+    }
+
+    public void sendFailure(ModuleContext moduleContext, Throwable cause) {
+        sendEvent(moduleContext, TOPIC_FAILURE, cause, null, null);
+    }
+
+    public void sendFailure(ModuleContext moduleContext, Throwable cause, String[] serviceObjectClass, String serviceFilter) {
+        sendEvent(moduleContext, TOPIC_FAILURE, cause, serviceObjectClass, serviceFilter);
+    }
+
+    public void sendEvent(ModuleContext moduleContext, String topic, Throwable cause, String[] serviceObjectClass, String serviceFilter) {
+        EventAdmin eventAdmin = getEventAdmin();
+        if (eventAdmin == null) {
+            return;
+        }
+
+        Bundle bundle = moduleContext.getBundleContext().getBundle();
+
+        Dictionary props = new Hashtable();
+        props.put("bundle.symbolicName", bundle.getSymbolicName());
+        props.put("bundle.id", bundle.getBundleId());
+        props.put("bundle", bundle);
+        props.put("bundle.version", "NA");
+        props.put("timestamp", System.currentTimeMillis());
+        props.put(ModuleContextEventConstants.EXTENDER_BUNDLE, "NA");
+        props.put(ModuleContextEventConstants.EXTENDER_ID, "NA");
+        props.put(ModuleContextEventConstants.EXTENDER_SYMBOLICNAME, "NA");
+        if (cause != null) {
+            props.put("exception", cause);
+        }
+        if (serviceObjectClass != null) {
+            props.put("service.objectClass", serviceObjectClass);
+        }
+        if (serviceFilter != null) {
+            props.put("service.filter", serviceFilter);
+        }
+
+        Event event = new Event(topic, props);
+        eventAdmin.postEvent(event);
+        System.out.println("Event sent: " + topic);
+    }
+
+    private EventAdmin getEventAdmin() {
+        return (EventAdmin)this.eventAdminServiceTracker.getService();
+    }
+
+    public void destroy() {
+        this.eventAdminServiceTracker.close();
+    }
+}

Modified: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Instanciator.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Instanciator.java?rev=764641&r1=764640&r2=764641&view=diff
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Instanciator.java (original)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Instanciator.java Mon Apr 13 22:34:49 2009
@@ -96,7 +96,7 @@
         if (v instanceof NullValue) {
             return null;
         } else if (v instanceof TypedStringValue) {
-            // TODO: type name ?
+            // TODO: TypedStringValue#getTypeName()
             return ((TypedStringValue) v).getStringValue();
         } else if (v instanceof ReferenceValue) {
             String componentName = ((ReferenceValue) v).getComponentName();
@@ -131,8 +131,7 @@
         } else if (v instanceof ComponentValue) {
             return createRecipe(((ComponentValue) v).getComponentMetadata());
         } else if (v instanceof PropertiesValue) {
-            // TODO
-            throw new IllegalStateException("Unsupported value: " + v.getClass().getName());
+            return ((PropertiesValue) v).getPropertiesValue();
         } else if (v instanceof ReferenceNameValue) {
             return ((ReferenceNameValue) v).getReferenceName();
         } else {

Modified: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/ModuleContextImpl.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/ModuleContextImpl.java?rev=764641&r1=764640&r2=764641&view=diff
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/ModuleContextImpl.java (original)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/ModuleContextImpl.java Mon Apr 13 22:34:49 2009
@@ -22,8 +22,12 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Set;
+import java.net.URL;
 
 import org.apache.felix.blueprint.namespace.ComponentDefinitionRegistryImpl;
+import org.apache.felix.blueprint.ModuleContextEventSender;
+import org.apache.xbean.recipe.Repository;
+import org.apache.xbean.recipe.ObjectGraph;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.blueprint.context.ModuleContext;
 import org.osgi.service.blueprint.context.NoSuchComponentException;
@@ -40,10 +44,34 @@
  */
 public class ModuleContextImpl implements ModuleContext {
 
-    private BundleContext bundleContext;
+    private final BundleContext bundleContext;
+    private final ModuleContextEventSender sender;
+    private final URL[] urls;
     private ComponentDefinitionRegistryImpl componentDefinitionRegistry;
 
-    public ModuleContextImpl() {
+    public ModuleContextImpl(BundleContext bundleContext, ModuleContextEventSender sender, URL[] urls) {
+        this.bundleContext = bundleContext;
+        this.sender = sender;
+        this.urls = urls;
+    }
+
+    public void create() {
+        sender.sendCreating(this);
+        try {
+            Parser parser = new Parser();
+            parser.parse(urls);
+            componentDefinitionRegistry = parser.getRegistry();
+            Repository repository = Instanciator.createRepository(componentDefinitionRegistry);
+            ObjectGraph graph = new ObjectGraph(repository);
+            graph.createAll(new ArrayList<String>(componentDefinitionRegistry.getComponentDefinitionNames()));
+            sender.sendCreated(this);
+        } catch (WaitForDependencyException e) {
+            sender.sendWaiting(this, null, null); // TODO: give correct args
+            // TODO: wait for dependency
+        } catch (Exception e) {
+            // TODO: pass the exception to the event
+            sender.sendFailure(this, e);
+        }
     }
 
     public Set<String> getComponentNames() {
@@ -92,4 +120,12 @@
     public BundleContext getBundleContext() {
         return bundleContext;
     }
+
+    public void destroy() {
+        sender.sendDestroying(this);
+        System.out.println("Module context destroyed: " + this.bundleContext);
+        // TODO: destroy all instances
+        sender.sendDestroyed(this);
+    }
+
 }

Modified: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Parser.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Parser.java?rev=764641&r1=764640&r2=764641&view=diff
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Parser.java (original)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/Parser.java Mon Apr 13 22:34:49 2009
@@ -42,7 +42,7 @@
 import org.w3c.dom.Attr;
 
 import org.apache.felix.blueprint.namespace.ComponentDefinitionRegistryImpl;
-import org.apache.felix.blueprint.namespace.NamespaceHandlerRegistry;
+import org.apache.felix.blueprint.NamespaceHandlerRegistry;
 import org.apache.felix.blueprint.reflect.ComponentValueImpl;
 import org.apache.felix.blueprint.reflect.ListValueImpl;
 import org.apache.felix.blueprint.reflect.LocalComponentMetadataImpl;
@@ -78,7 +78,6 @@
 import org.osgi.service.blueprint.reflect.ComponentMetadata;
 import org.osgi.service.blueprint.reflect.CollectionBasedServiceReferenceComponentMetadata;
 import org.osgi.service.blueprint.reflect.ArrayValue;
-import org.xml.sax.EntityResolver;
 import org.xml.sax.InputSource;
 
 /**
@@ -181,7 +180,7 @@
     private DocumentBuilderFactory documentBuilderFactory;
     private ComponentDefinitionRegistryImpl registry;
     private ConversionService conversionService;
-    private NamespaceHandlerRegistry namespaceHandlerRegistry;  
+    private NamespaceHandlerRegistry namespaceHandlerRegistry;
     private int nameCounter;
     private String defaultTimeout;
     private String defaultAvailability;

Added: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/WaitForDependencyException.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/WaitForDependencyException.java?rev=764641&view=auto
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/WaitForDependencyException.java (added)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/context/WaitForDependencyException.java Mon Apr 13 22:34:49 2009
@@ -0,0 +1,18 @@
+package org.apache.felix.blueprint.context;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: gnodet
+ * Date: Apr 14, 2009
+ * Time: 12:17:56 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class WaitForDependencyException extends Exception {
+
+    public WaitForDependencyException() {
+    }
+
+    public WaitForDependencyException(String message) {
+        super(message);
+    }
+}

Modified: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/convert/ConversionServiceImpl.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/convert/ConversionServiceImpl.java?rev=764641&r1=764640&r2=764641&view=diff
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/convert/ConversionServiceImpl.java (original)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/convert/ConversionServiceImpl.java Mon Apr 13 22:34:49 2009
@@ -1,122 +1,141 @@
-/*
- * 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
+/**
+ *  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
+ *     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.
+ *  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.felix.blueprint.convert;
 
-import java.util.List;
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
-import java.util.Map;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Properties;
 import java.util.regex.Pattern;
-import java.util.concurrent.ConcurrentHashMap;
-import java.lang.reflect.Constructor;
-import java.io.StringReader;
-import java.io.Reader;
-import java.io.ByteArrayInputStream;
 
 import org.osgi.service.blueprint.convert.ConversionService;
 import org.osgi.service.blueprint.convert.Converter;
 
-/**
- * TODO: javadoc
- *
- * @author <a href="mailto:dev@felix.apache.org">Apache Felix Project</a>
- * @version $Rev: 760378 $, $Date: 2009-03-31 11:31:38 +0200 (Tue, 31 Mar 2009) $
- */
 public class ConversionServiceImpl implements ConversionService {
 
-    private static final Map<Class, Class> primitives;
-    private List<Converter> converters = new ArrayList<Converter>();
-
-    static {
-        primitives = new HashMap<Class, Class>();
-        primitives.put(byte.class, Byte.class);
-        primitives.put(int.class, Integer.class);
-        primitives.put(long.class, Long.class);
-        primitives.put(float.class, Float.class);
-        primitives.put(double.class, Double.class);
-        primitives.put(short.class, Short.class);
-        primitives.put(char.class, Character.class);
-        primitives.put(boolean.class, Boolean.class);
-    }
+    private Map<Class, List<Converter>> convertersMap = new HashMap<Class, List<Converter>>();
 
-    public ConversionServiceImpl() {
+    public void registerConverter(Converter converter) {
+        Class type = converter.getTargetClass();
+        List<Converter> converters = convertersMap.get(type);
+        if (converters == null) {
+            converters = new ArrayList<Converter>();
+            convertersMap.put(type, converters);
+        }
+        converters.add(converter);
     }
 
     public Object convert(Object fromValue, Class toType) throws Exception {
-        if (fromValue == null) {
-            return null;
+        Converter converter = lookupConverter(toType);
+        if (converter == null) {
+            return convertDefault(fromValue, toType);
+        } else {
+            return converter.convert(fromValue);
         }
-        // Check converters
-        for (Converter converter : converters) {
-            if (converter.getTargetClass().equals(toType)) {
-                return converter.convert(fromValue);
-            }
+    }
+
+    private Converter lookupConverter(Class toType) {
+        // do explicit lookup
+        List<Converter> converters = convertersMap.get(toType);
+        if (converters != null && !converters.isEmpty()) {
+            return converters.get(0);
         }
-        // Default conversion
-        if (fromValue instanceof String) {
-            String fromString = (String) fromValue;
-            if (primitives.containsKey(toType)) {
-                toType = primitives.get(toType);
-            }
-            // Boolean
-            if (toType.equals(Boolean.class)) {
-                fromString = fromString.toLowerCase();
-                if (fromString.equals("true") || fromString.equals("yes") || fromString.equals("on")) {
-                    return Boolean.TRUE;
-                } else if (fromString.equals("false") || fromString.equals("no") || fromString.equals("off")) {
-                    return Boolean.FALSE;
-                } else {
-                    throw new IllegalArgumentException("Illegal boolean value: " + fromString);
-                }
-            }
-            // Character
-            if (toType.equals(Character.class)) {
-                if (fromString.length() == 1) {
-                    return fromString.charAt(0);
-                } else {
-                    throw new IllegalArgumentException("Conversion from String to Character must have a strig argument of length equals to 1");
-                }
-            }
-            // Locale
-            if (toType.equals(Locale.class)) {
-                // TODO
-            }
-            // Properties
-            if (toType.equals(Properties.class)) {
-                Properties props = new Properties();
-                props.load(new ByteArrayInputStream(fromString.getBytes()));
-                return props;
-            }
-            // Pattern
-            if (toType.equals(Pattern.class)) {
-                return Pattern.compile(fromString);
-            }
-            // Public constructor
-            try {
-                Constructor constructor = toType.getConstructor(String.class);
-                return constructor.newInstance(fromString);
-            } catch (NoSuchMethodException e) {
-                // Ignore
+
+        // try to find converter that matches the type
+        for (Map.Entry<Class, List<Converter>> entry : convertersMap.entrySet()) {
+            Class converterClass = entry.getKey();
+            if (toType.isAssignableFrom(converterClass)) {
+                return entry.getValue().get(0);
             }
         }
+
         return null;
     }
-}
+
+    private Object convertDefault(Object fromValue, Class toType) throws Exception {
+        String value = (String)fromValue;
+        if (Locale.class == toType) {
+            String[] tokens = value.split("_");
+            if (tokens.length == 1) {
+                return new Locale(tokens[0]);
+            } else if (tokens.length == 2) {
+                return new Locale(tokens[0], tokens[1]);
+            } else if (tokens.length == 3) {
+                return new Locale(tokens[0], tokens[1], tokens[2]);
+            } else {
+                throw new Exception("Invalid locale string:" + value);
+            }
+        } else if (Pattern.class == toType) {
+            return Pattern.compile(value);
+        } else if (Properties.class == toType) {
+            Properties props = new Properties();
+            ByteArrayInputStream in = new ByteArrayInputStream(value.getBytes("UTF8"));
+            props.load(in);
+            return props;
+        } else if (Boolean.class == toType || boolean.class == toType) {
+            if ("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value)) {
+                return Boolean.TRUE;
+            } else if ("no".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value) || "off".equalsIgnoreCase(value)) {
+                return Boolean.FALSE;
+            } else {
+                throw new RuntimeException("Invalid boolean value: " + value);
+            }
+        } else if (Integer.class == toType || int.class == toType) {
+            return Integer.valueOf(value);
+        } else if (Short.class == toType || short.class == toType) {
+            return Short.valueOf(value);
+        } else if (Long.class == toType || long.class == toType) {
+            return Long.valueOf(value);
+        } else if (Float.class == toType || float.class == toType) {
+            return Float.valueOf(value);
+        } else if (Double.class == toType || double.class == toType) {
+            return Double.valueOf(value);
+        } else if (Character.class == toType || char.class == toType) {
+            if (value.length() == 1) {
+                return Character.valueOf(value.charAt(0));
+            } else {
+                throw new Exception("Invalid value for character type: " + value);
+            }
+        } else if (Byte.class == toType || byte.class == toType) {
+            return Byte.valueOf(value);
+        } else {
+            return createObject(value, toType);
+        }
+    }
+
+    private Object createObject(String value, Class type) throws Exception {
+        Constructor constructor = null;
+        try {
+            constructor = type.getConstructor(String.class);
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException("Unable to convert to " + type);
+        }
+        try {
+            return constructor.newInstance(value);
+        } catch (InvocationTargetException e) {
+            throw new Exception("Unable to convert ", e.getTargetException());
+        } catch (Exception e) {
+            throw new Exception("Unable to convert ", e);
+        }
+    }
+
+}
\ No newline at end of file

Modified: geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistryImpl.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistryImpl.java?rev=764641&r1=764640&r2=764641&view=diff
==============================================================================
--- geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistryImpl.java (original)
+++ geronimo/sandbox/gnodet/blueprint/org.apache.felix.blueprint/src/main/java/org/apache/felix/blueprint/namespace/NamespaceHandlerRegistryImpl.java Mon Apr 13 22:34:49 2009
@@ -20,9 +20,17 @@
 
 import java.util.Map;
 import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ConcurrentHashMap;
 import java.net.URI;
 
 import org.osgi.service.blueprint.namespace.NamespaceHandler;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.apache.felix.blueprint.NamespaceHandlerRegistry;
 
 /**
  * TODO: javadoc
@@ -30,14 +38,53 @@
  * @author <a href="mailto:dev@felix.apache.org">Apache Felix Project</a>
  * @version $Rev: 760378 $, $Date: 2009-03-31 11:31:38 +0200 (Tue, 31 Mar 2009) $
  */
-public class NamespaceHandlerRegistryImpl implements NamespaceHandlerRegistry {
+public class NamespaceHandlerRegistryImpl implements NamespaceHandlerRegistry, ServiceTrackerCustomizer {
 
     public static final String NAMESPACE = "org.osgi.blueprint.namespace";
 
+    private final BundleContext bundleContext;
     private final Map<URI, NamespaceHandler> handlers;
+    private final List<Runnable> runnables;
+    private final ServiceTracker tracker;
 
-    public NamespaceHandlerRegistryImpl() {
-        handlers = new HashMap<URI, NamespaceHandler>();
+    public NamespaceHandlerRegistryImpl(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+        handlers = new ConcurrentHashMap<URI, NamespaceHandler>();
+        runnables = new CopyOnWriteArrayList<Runnable>();
+        tracker = new ServiceTracker(bundleContext, NamespaceHandler.class.getName(), this);
+    }
+
+    public Object addingService(ServiceReference reference) {
+        NamespaceHandler handler = (NamespaceHandler) bundleContext.getService(reference);
+        Map props = new HashMap();
+        for (String name : reference.getPropertyKeys()) {
+            props.put(name, reference.getProperty(name));
+        }
+        try {
+            registerHandler(handler, props);
+            return handler;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public void modifiedService(ServiceReference reference, Object service) {
+        removedService(reference, service);
+        addingService(reference);
+    }
+
+    public void removedService(ServiceReference reference, Object service) {
+        NamespaceHandler handler = (NamespaceHandler) service;
+        Map props = new HashMap();
+        for (String name : reference.getPropertyKeys()) {
+            props.put(name, reference.getProperty(name));
+        }
+        try {
+            unregisterHandler(handler, props);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
     }
 
     public void registerHandler(NamespaceHandler handler, Map properties) throws Exception {
@@ -51,6 +98,10 @@
             for (URI uri : (URI[]) ns) {
                 handlers.put(uri, handler);
             }
+            for (Runnable r : runnables) {
+                r.run();
+            }
+
         } else {
             throw new IllegalArgumentException("NamespaceHandler service does not have an associated " + NAMESPACE + " property defined");
         }
@@ -67,6 +118,9 @@
             for (URI uri : (URI[]) ns) {
                 handlers.remove(uri);
             }
+            for (Runnable r : runnables) {
+                r.run();
+            }
         } else {
             throw new IllegalArgumentException("NamespaceHandler service does not have an associated " + NAMESPACE + " property defined");
         }
@@ -76,4 +130,11 @@
         return handlers.get(uri);
     }
 
+    public void addCallback(Runnable runnable) {
+        runnables.add(runnable);
+    }
+
+    public void destroy() {
+        tracker.close();
+    }
 }