geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gno...@apache.org
Subject svn commit: r767090 [1/2] - in /geronimo/sandbox/blueprint: blueprint-core/src/main/java/org/apache/geronimo/blueprint/ blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils...
Date Tue, 21 Apr 2009 09:46:41 GMT
Author: gnodet
Date: Tue Apr 21 09:46:41 2009
New Revision: 767090

URL: http://svn.apache.org/viewvc?rev=767090&view=rev
Log:
Implement ref-list and ref-set

Added:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Destroyable.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/AbstractServiceReferenceRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/CollectionBasedServiceReferenceRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceUnregisteredException.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/UnaryServiceReferenceRecipe.java
      - copied, changed from r766654, geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReferenceServiceRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicCollection.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicList.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSet.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedList.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedSet.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/ReflectionUtils.java   (contents, props changed)
      - copied, changed from r766654, geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReflectionUtils.java
    geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/utils/
    geronimo/sandbox/blueprint/blueprint-core/src/test/java/org/apache/geronimo/blueprint/utils/DynamicCollectionTest.java
Removed:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/LifeCycle.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReferenceServiceRecipe.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReflectionUtils.java
Modified:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Instanciator.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceRegistrationProxy.java
    geronimo/sandbox/blueprint/blueprint-itests/src/test/java/org/apache/geronimo/blueprint/itests/TestReferences.java
    geronimo/sandbox/blueprint/blueprint-sample/src/main/resources/OSGI-INF/blueprint/config.xml

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Destroyable.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Destroyable.java?rev=767090&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Destroyable.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/Destroyable.java Tue Apr 21 09:46:41 2009
@@ -0,0 +1,30 @@
+/**
+ * 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;
+
+/**
+ * Interface used as a callback to destroy a given object.
+ *
+ * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
+ * @version $Rev: 766508 $, $Date: 2009-04-19 22:09:27 +0200 (Sun, 19 Apr 2009) $
+ */
+public interface Destroyable {
+
+    void destroy() throws Exception;
+}

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/AbstractServiceReferenceRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/AbstractServiceReferenceRecipe.java?rev=767090&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/AbstractServiceReferenceRecipe.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/AbstractServiceReferenceRecipe.java Tue Apr 21 09:46:41 2009
@@ -0,0 +1,267 @@
+/*
+ * 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.List;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.Map;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Collection;
+import java.lang.reflect.Method;
+
+import org.apache.xbean.recipe.AbstractRecipe;
+import org.apache.xbean.recipe.Recipe;
+import org.apache.xbean.recipe.ConstructionException;
+import org.apache.geronimo.blueprint.ModuleContextEventSender;
+import org.apache.geronimo.blueprint.BlueprintConstants;
+import org.apache.geronimo.blueprint.Destroyable;
+import org.apache.geronimo.blueprint.utils.ReflectionUtils;
+import org.osgi.service.blueprint.context.ModuleContext;
+import org.osgi.service.blueprint.reflect.ServiceReferenceComponentMetadata;
+import org.osgi.service.blueprint.reflect.BindingListenerMetadata;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceEvent;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.Dispatcher;
+
+/**
+ * Abstract class for service reference recipes.
+ *
+ * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
+ * @version $Rev: 760378 $, $Date: 2009-03-31 11:31:38 +0200 (Tue, 31 Mar 2009) $
+ */
+public abstract class AbstractServiceReferenceRecipe extends AbstractRecipe implements ServiceListener, Destroyable {
+
+    protected final ModuleContext moduleContext;
+    protected final ModuleContextEventSender sender;
+    protected final ServiceReferenceComponentMetadata metadata;
+    protected final Recipe listenersRecipe;
+    protected List<Listener> listeners;
+    private String filter;
+    protected final ClassLoader proxyClassLoader;
+
+    protected AbstractServiceReferenceRecipe(ModuleContext moduleContext,
+                                             ModuleContextEventSender sender,
+                                             ServiceReferenceComponentMetadata metadata,
+                                             Recipe listenersRecipe) {
+        this.moduleContext = moduleContext;
+        this.sender = sender;
+        this.metadata = metadata;
+        this.listenersRecipe = listenersRecipe;
+        // Create a ClassLoader delegating to the bundle, but also being able to see our bundle classes
+        // so that the created proxy can access cglib classes.
+        this.proxyClassLoader = new BundleDelegatingClassLoader(moduleContext.getBundleContext().getBundle(),
+                                                                getClass().getClassLoader());
+    }
+
+    protected String getOsgiFilter() {
+        if (filter == null) {
+            List<String> members = new ArrayList<String>();
+            // Handle filter
+            String flt = metadata.getFilter();
+            if (flt != null && flt.length() > 0) {
+                if (!flt.startsWith("(")) {
+                    flt = "(" + flt + ")";
+                }
+                members.add(flt);
+            }
+            // Handle interfaces
+            Set<String> interfaces = (Set<String>) metadata.getInterfaceNames();
+            if (interfaces != null && !interfaces.isEmpty()) {
+                for (String itf : interfaces) {
+                    members.add("(" + Constants.OBJECTCLASS + "=" + itf + ")");
+                }
+            }
+            // Handle component name
+            String componentName = metadata.getComponentName();
+            if (componentName != null && componentName.length() > 0) {
+                members.add("(" + BlueprintConstants.COMPONENT_NAME_PROPERTY + "=" + componentName + ")");
+            }
+            // Create filter
+            if (members.isEmpty()) {
+                throw new IllegalStateException("No constraints were specified on the service reference");
+            }
+            StringBuilder sb = new StringBuilder("(&");
+            for (String member : members) {
+                sb.append(member);
+            }
+            sb.append(")");
+            filter = sb.toString();
+        }
+        return filter;
+    }
+
+    protected void createListeners() throws ClassNotFoundException {
+        if (listenersRecipe != null) {
+            listeners = (List<Listener>) listenersRecipe.create(proxyClassLoader);
+            for (Listener listener : listeners) {
+                listener.init(getAllClasses(metadata.getInterfaceNames()));
+            }
+        } else {
+            listeners = Collections.emptyList();
+        }
+    }
+
+    protected List<Class> getAllClasses(Iterable<String> interfaceNames) throws ClassNotFoundException {
+        List<Class> classes = new ArrayList<Class>();
+        for (String name : interfaceNames) {
+            Class clazz = proxyClassLoader.loadClass(name);
+            classes.add(clazz);
+        }
+        return classes;
+    }
+
+    protected Class[] getInterfaces(Iterable<String> interfaceNames) throws ClassNotFoundException {
+        List<Class> interfaces = new ArrayList<Class>();
+        for (String name : interfaceNames) {
+            Class clazz = proxyClassLoader.loadClass(name);
+            if (clazz.isInterface()) {
+                interfaces.add(clazz);
+            }
+        }
+        return interfaces.toArray(new Class[interfaces.size()]);
+    }
+
+    protected Class getTargetClass(Iterable<String> interfaceNames) throws ClassNotFoundException {
+        Class root = Object.class;
+        for (String name : interfaceNames) {
+            Class clazz = proxyClassLoader.loadClass(name);
+            if (!clazz.isInterface()) {
+                if (root == Object.class) {
+                    root = clazz;
+                    continue;
+                }
+                // Check that all classes are in the same hierarchy
+                for (Class p = clazz; p != Object.class; p = p.getSuperclass()) {
+                    if (p == root) {
+                        root = clazz;
+                        continue;
+                    }
+                }
+                for (Class p = root; p != Object.class; p = p.getSuperclass()) {
+                    if (p == clazz) {
+                        continue;
+                    }
+                }
+                throw new ConstructionException("Classes " + root.getClass().getName() + " and " + clazz.getName() + " are not in the same hierarchy");
+            }
+        }
+        return root;
+    }
+
+    protected Object createProxy(Dispatcher dispatcher, Iterable<String> interfaces) throws Exception {
+        Enhancer e = new Enhancer();
+        e.setClassLoader(proxyClassLoader);
+        e.setSuperclass(getTargetClass(interfaces));
+        e.setInterfaces(getInterfaces(interfaces));
+        e.setInterceptDuringConstruction(false);
+        e.setCallback(dispatcher);
+        e.setUseFactory(false);
+        return e.create();
+    }
+
+    public void serviceChanged(ServiceEvent event) {
+        int eventType = event.getType();
+        ServiceReference ref = event.getServiceReference();
+        switch (eventType) {
+            case ServiceEvent.REGISTERED:
+            case ServiceEvent.MODIFIED:
+                track(ref);
+                break;
+            case ServiceEvent.UNREGISTERING:
+                untrack(ref);
+                break;
+        }
+    }
+
+    protected abstract void track(ServiceReference reference);
+
+    protected abstract void untrack(ServiceReference reference);
+
+    public static class Listener {
+
+        /* Inject by ObjectRecipe */
+        private Object listener;
+        /* Inject by ObjectRecipe */
+        private BindingListenerMetadata metadata;
+
+        private Set<Method> bindMethodsOneArg = new HashSet<Method>();
+        private Set<Method> bindMethodsTwoArgs = new HashSet<Method>();
+        private Set<Method> unbindMethodsOneArg = new HashSet<Method>();
+        private Set<Method> unbindMethodsTwoArgs = new HashSet<Method>();
+
+        public void init(Collection<Class> classes) {
+            Set<Class> clazzes = new HashSet<Class>(classes);
+            clazzes.add(Object.class);
+            Class listenerClass = listener.getClass();
+            String bindName = metadata.getBindMethodName();
+            if (bindName != null) {
+                bindMethodsOneArg.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, bindName, new Class[] { ServiceReference.class }));
+                for (Class clazz : clazzes) {
+                    bindMethodsTwoArgs.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, bindName, new Class[] { clazz, Map.class }));
+                }
+            }
+            String unbindName = metadata.getUnbindMethodName();
+            if (unbindName != null) {
+                unbindMethodsOneArg.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, new Class[] { ServiceReference.class }));
+                for (Class clazz : clazzes) {
+                    unbindMethodsTwoArgs.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, new Class[] { clazz, Map.class }));
+                }
+            }
+        }
+
+        public void bind(ServiceReference reference, Object service) {
+            invokeMethods(bindMethodsOneArg, bindMethodsTwoArgs, reference, service);
+        }
+
+        public void unbind(ServiceReference reference, Object service) {
+            invokeMethods(unbindMethodsOneArg, unbindMethodsTwoArgs, reference, service);
+        }
+
+        private void invokeMethods(Set<Method> oneArgMethods, Set<Method> twoArgsMethods, ServiceReference reference, Object service) {
+            for (Method method : oneArgMethods) {
+                try {
+                    method.invoke(listener, reference);
+                } catch (Exception e) {
+                    e.printStackTrace(); // TODO: log
+                }
+            }
+            Map<String, Object> props = null;
+            for (Method method : twoArgsMethods) {
+                if (props == null) {
+                    props = new HashMap<String, Object>();
+                    for (String name : reference.getPropertyKeys()) {
+                        props.put(name, reference.getProperty(name));
+                    }
+                }
+                try {
+                    method.invoke(listener, service, props);
+                } catch (Exception e) {
+                    e.printStackTrace(); // TODO: log
+                }
+            }
+        }
+    }
+
+}

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/CollectionBasedServiceReferenceRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/CollectionBasedServiceReferenceRecipe.java?rev=767090&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/CollectionBasedServiceReferenceRecipe.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/CollectionBasedServiceReferenceRecipe.java Tue Apr 21 09:46:41 2009
@@ -0,0 +1,505 @@
+/*
+ * 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.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.AbstractList;
+import java.util.Iterator;
+import java.util.AbstractSet;
+import java.util.RandomAccess;
+import java.util.SortedSet;
+import java.util.Set;
+import java.util.AbstractCollection;
+import java.util.ArrayList;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import net.sf.cglib.proxy.Dispatcher;
+import org.apache.geronimo.blueprint.Destroyable;
+import org.apache.geronimo.blueprint.ModuleContextEventSender;
+import org.apache.geronimo.blueprint.utils.DynamicSortedList;
+import org.apache.geronimo.blueprint.utils.DynamicList;
+import org.apache.geronimo.blueprint.utils.DynamicSet;
+import org.apache.geronimo.blueprint.utils.DynamicSortedSet;
+import org.apache.geronimo.blueprint.utils.DynamicCollection;
+import org.apache.xbean.recipe.ConstructionException;
+import org.apache.xbean.recipe.ExecutionContext;
+import org.apache.xbean.recipe.Recipe;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.blueprint.context.ModuleContext;
+import org.osgi.service.blueprint.reflect.CollectionBasedServiceReferenceComponentMetadata;
+
+/**
+ * A recipe to create a managed collection of service references
+ *
+ * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
+ * @version $Rev: 760378 $, $Date: 2009-03-31 11:31:38 +0200 (Tue, 31 Mar 2009) $
+ */
+public class CollectionBasedServiceReferenceRecipe extends AbstractServiceReferenceRecipe {
+
+    private final CollectionBasedServiceReferenceComponentMetadata metadata;
+    private final Recipe comparatorRecipe;
+    private Comparator comparator;
+
+    private ManagedCollection collection;
+
+    public CollectionBasedServiceReferenceRecipe(ModuleContext moduleContext,
+                                                 ModuleContextEventSender sender,
+                                                 CollectionBasedServiceReferenceComponentMetadata metadata,
+                                                 Recipe listenersRecipe,
+                                                 Recipe comparatorRecipe) {
+        super(moduleContext, sender, metadata, listenersRecipe);
+        this.metadata = metadata;
+        this.comparatorRecipe = comparatorRecipe;
+    }
+
+    public boolean canCreate(Type type) {
+        return true;
+    }
+
+    protected Object internalCreate(Type expectedType, boolean lazyRefAllowed) throws ConstructionException {
+        try {
+
+            if (comparatorRecipe != null) {
+                comparator = (Comparator) comparatorRecipe.create(proxyClassLoader);
+            } else if (metadata.getOrderingComparisonBasis() != 0) {
+                comparator = new NaturalOrderComparator();
+            }
+            boolean orderReferences = metadata.getOrderingComparisonBasis() == CollectionBasedServiceReferenceComponentMetadata.ORDER_BASIS_SERVICE_REFERENCES;
+            boolean memberReferences = metadata.getMemberType() == CollectionBasedServiceReferenceComponentMetadata.MEMBER_TYPE_SERVICE_REFERENCES;
+            if (metadata.getCollectionType() == List.class) {
+                if (comparator != null) {
+                    collection = new ManagedSortedList(memberReferences, orderReferences, comparator);
+                } else {
+                    collection = new ManagedList(memberReferences);
+                }
+            } else if (metadata.getCollectionType() == Set.class) {
+                if (comparator != null) {
+                    collection = new ManagedSortedSet(memberReferences, orderReferences, comparator);
+                } else {
+                    collection = new ManagedSet(memberReferences);
+                }
+            } else {
+                throw new IllegalArgumentException("Unsupported collection type " + metadata.getCollectionType().getName());
+            }
+
+            // Create the listeners and initialize them
+            createListeners();
+
+            // Add the created proxy to the context
+            if (getName() != null) {
+                ExecutionContext.getContext().addObject(getName(), collection);
+            }
+
+            // Start tracking the service
+            moduleContext.getBundleContext().addServiceListener(this, getOsgiFilter());
+            retrack();
+
+            return collection;
+        } catch (Throwable t) {
+            t.printStackTrace();
+            throw new ConstructionException(t);
+        }
+    }
+
+    public void destroy() throws Exception {
+        moduleContext.getBundleContext().removeServiceListener(this);
+        List<ServiceDispatcher> dispatchers = new ArrayList<ServiceDispatcher>(collection.getDispatchers());
+        for (ServiceDispatcher dispatcher : dispatchers) {
+            untrack(dispatcher.reference);
+        }
+    }
+
+    private void retrack() {
+        try {
+            ServiceReference[] refs = moduleContext.getBundleContext().getServiceReferences(null, getOsgiFilter());
+            if (refs != null) {
+                for (ServiceReference ref : refs) {
+                    track(ref);
+                }
+            }
+        } catch (InvalidSyntaxException e) {
+            // Ignore, should never happen
+        }
+    }
+
+    protected void track(ServiceReference reference) {
+        try {
+            ServiceDispatcher dispatcher = new ServiceDispatcher(reference);
+            dispatcher.proxy = createProxy(dispatcher, Arrays.asList((String[]) reference.getProperty(Constants.OBJECTCLASS)));
+            collection.addDispatcher(dispatcher);
+            for (Listener listener : listeners) {
+                listener.bind(dispatcher.reference, dispatcher.proxy);
+            }
+        } catch (Throwable t) {
+            t.printStackTrace(); // TODO: log
+        }
+    }
+
+    protected void untrack(ServiceReference reference) {
+        ServiceDispatcher dispatcher = collection.findDispatcher(reference);
+        if (dispatcher != null) {
+            for (Listener listener : listeners) {
+                listener.unbind(dispatcher.reference, dispatcher.proxy);
+            }
+            collection.removeDispatcher(dispatcher);
+            dispatcher.destroy();
+        }
+    }
+
+    public static class NaturalOrderComparator implements Comparator<Comparable> {
+
+        public int compare(Comparable o1, Comparable o2) {
+            return o1.compareTo(o2);
+        }
+
+    }
+
+
+    public static class ServiceDispatcher implements Dispatcher, Destroyable {
+
+        public ServiceReference reference;
+        public Object service;
+        public Object proxy;
+
+        public ServiceDispatcher(ServiceReference reference) throws Exception {
+            this.reference = reference;
+            this.service = reference.getBundle().getBundleContext().getService(reference);
+        }
+
+        public void destroy() {
+            if (reference != null) {
+                reference.getBundle().getBundleContext().ungetService(reference);
+                service = null;
+                proxy = null;
+            }
+        }
+
+        public Object loadObject() throws Exception {
+            if (service == null) {
+                throw new ServiceUnregisteredException();
+            }
+            return service;
+        }
+    }
+
+    public static class DispatcherComparator implements Comparator<ServiceDispatcher> {
+
+        private final Comparator comparator;
+        private final boolean orderingReferences;
+
+        public DispatcherComparator(Comparator comparator, boolean orderingReferences) {
+            this.comparator = comparator;
+            this.orderingReferences = orderingReferences;
+        }
+
+        public int compare(ServiceDispatcher d1, ServiceDispatcher d2) {
+            return comparator.compare(getOrdering(d1), getOrdering(d2));
+        }
+
+        protected Object getOrdering(ServiceDispatcher d) {
+            return orderingReferences ? d.reference : d.proxy;
+        }
+
+    }
+
+    public static class ManagedCollection extends AbstractCollection {
+
+        protected final boolean references;
+        protected final DynamicCollection<ServiceDispatcher> dispatchers;
+
+        public ManagedCollection(boolean references, DynamicCollection<ServiceDispatcher> dispatchers) {
+            this.references = references;
+            this.dispatchers = dispatchers;
+        }
+
+        public boolean addDispatcher(ServiceDispatcher dispatcher) {
+            return dispatchers.add(dispatcher);
+        }
+
+        public boolean removeDispatcher(ServiceDispatcher dispatcher) {
+            return dispatchers.remove(dispatcher);
+        }
+
+        public DynamicCollection<ServiceDispatcher> getDispatchers() {
+            return dispatchers;
+        }
+
+        public ServiceDispatcher findDispatcher(ServiceReference reference) {
+            for (ServiceDispatcher dispatcher : dispatchers) {
+                if (dispatcher.reference == reference) {
+                    return dispatcher;
+                }
+            }
+            return null;
+        }
+
+        public Iterator iterator() {
+            return new ManagedIterator(dispatchers.iterator());
+        }
+
+        public int size() {
+            return dispatchers.size();
+        }
+
+        protected Object getMember(ServiceDispatcher d) {
+            return references ? d.reference : d.proxy;
+        }
+
+        @Override
+        public boolean add(Object o) {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        @Override
+        public boolean remove(Object o) {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        @Override
+        public boolean addAll(Collection c) {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        @Override
+        public void clear() {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        @Override
+        public boolean retainAll(Collection c) {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        @Override
+        public boolean removeAll(Collection c) {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        public class ManagedIterator implements Iterator {
+
+            private final Iterator<ServiceDispatcher> iterator;
+
+            public ManagedIterator(Iterator<ServiceDispatcher> iterator) {
+                this.iterator = iterator;
+            }
+
+            public boolean hasNext() {
+                return iterator.hasNext();
+            }
+
+            public Object next() {
+                return getMember(iterator.next());
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException("This collection is read only");
+            }
+        }
+
+    }
+
+
+    public static class ManagedList extends ManagedCollection implements List, RandomAccess {
+
+        protected DynamicList<ServiceDispatcher> dispatchers;
+
+        public ManagedList(boolean references) {
+            this(references,  new DynamicList<ServiceDispatcher>());
+        }
+
+        protected ManagedList(boolean references, DynamicList<ServiceDispatcher> dispatchers) {
+            super(references, dispatchers);
+            this.dispatchers = dispatchers;
+        }
+
+        @Override
+        public int size() {
+            return dispatchers.size();
+        }
+
+        public Object get(int index) {
+            return getMember(dispatchers.get(index));
+        }
+
+        public int indexOf(Object o) {
+            if (o == null) {
+                throw new NullPointerException();
+            }
+            ListIterator e = listIterator();
+            while (e.hasNext()) {
+                if (o.equals(e.next())) {
+                    return e.previousIndex();
+                }
+            }
+            return -1;
+        }
+
+        public int lastIndexOf(Object o) {
+            if (o == null) {
+                throw new NullPointerException();
+            }
+            ListIterator e = listIterator(size());
+            while (e.hasPrevious()) {
+                if (o.equals(e.previous())) {
+                    return e.nextIndex();
+                }
+            }
+            return -1;
+        }
+
+        public ListIterator listIterator() {
+            return listIterator(0);
+        }
+
+        public ListIterator listIterator(int index) {
+            return new ManagedListIterator(dispatchers.listIterator(index));
+        }
+
+        public List<ServiceDispatcher> subList(int fromIndex, int toIndex) {
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        public Object set(int index, Object element) {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        public void add(int index, Object element) {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        public Object remove(int index) {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        public boolean addAll(int index, Collection c) {
+            throw new UnsupportedOperationException("This collection is read only");
+        }
+
+        public class ManagedListIterator implements ListIterator {
+
+            protected final ListIterator<ServiceDispatcher> iterator;
+
+            public ManagedListIterator(ListIterator<ServiceDispatcher> iterator) {
+                this.iterator = iterator;
+            }
+
+            public boolean hasNext() {
+                return iterator.hasNext();
+            }
+
+            public Object next() {
+                return getMember(iterator.next());
+            }
+
+            public boolean hasPrevious() {
+                return iterator.hasPrevious();
+            }
+
+            public Object previous() {
+                return getMember(iterator.previous());
+            }
+
+            public int nextIndex() {
+                return iterator.nextIndex();
+            }
+
+            public int previousIndex() {
+                return iterator.previousIndex();
+            }
+
+            public void remove() {
+                throw new UnsupportedOperationException("This collection is read only");
+            }
+
+            public void set(Object o) {
+                throw new UnsupportedOperationException("This collection is read only");
+            }
+
+            public void add(Object o) {
+                throw new UnsupportedOperationException("This collection is read only");
+            }
+        }
+
+    }
+
+    public static class ManagedSortedList extends ManagedList {
+
+        public ManagedSortedList(boolean references, boolean orderingReferences, Comparator comparator) {
+            super(references, new DynamicSortedList<ServiceDispatcher>(new DispatcherComparator(comparator, orderingReferences)));
+        }
+
+    }
+
+    public static class ManagedSet extends ManagedCollection implements Set {
+
+        public ManagedSet(boolean references) {
+            this(references, new DynamicSet<ServiceDispatcher>());
+        }
+
+        protected ManagedSet(boolean references, DynamicSet<ServiceDispatcher> dispatchers) {
+            super(references, dispatchers);
+        }
+
+    }
+
+    public static class ManagedSortedSet extends ManagedSet implements SortedSet {
+
+        protected final DynamicSortedSet<ServiceDispatcher> dispatchers;
+        protected final Comparator comparator;
+
+        public ManagedSortedSet(boolean references, boolean orderingReferences, Comparator comparator) {
+            super(references, new DynamicSortedSet<ServiceDispatcher>(new DispatcherComparator(comparator, orderingReferences)));
+            this.dispatchers = (DynamicSortedSet<ServiceDispatcher>) super.dispatchers;
+            this.comparator =  comparator;
+        }
+
+        public Comparator comparator() {
+            return comparator;
+        }
+
+        public SortedSet subSet(Object fromElement, Object toElement) {
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        public SortedSet headSet(Object toElement) {
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        public SortedSet tailSet(Object fromElement) {
+            throw new UnsupportedOperationException("Not implemented");
+        }
+
+        public Object first() {
+            return getMember(dispatchers.first());
+        }
+
+        public Object last() {
+            return getMember(dispatchers.last());
+        }
+
+    }
+
+}

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Instanciator.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Instanciator.java?rev=767090&r1=767089&r2=767090&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Instanciator.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Instanciator.java Tue Apr 21 09:46:41 2009
@@ -26,13 +26,13 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Comparator;
 
 import org.apache.geronimo.blueprint.namespace.ComponentDefinitionRegistryImpl;
 import org.apache.geronimo.blueprint.reflect.ServiceExportComponentMetadataImpl;
 import org.apache.xbean.recipe.ArrayRecipe;
 import org.apache.xbean.recipe.CollectionRecipe;
 import org.apache.xbean.recipe.ConstructionException;
-import org.apache.xbean.recipe.DefaultRepository;
 import org.apache.xbean.recipe.MapRecipe;
 import org.apache.xbean.recipe.ObjectRecipe;
 import org.apache.xbean.recipe.Option;
@@ -140,15 +140,33 @@
                     cr.add(createRecipe(listener));
                 }
             }
-            ReferenceServiceRecipe recipe = new ReferenceServiceRecipe(moduleContext,
+            UnaryServiceReferenceRecipe recipe = new UnaryServiceReferenceRecipe(moduleContext,
                                                                        moduleContext.getSender(),
                                                                        metadata,
                                                                        cr);
             recipe.setName(component.getName());
             return recipe;
         } else if (component instanceof CollectionBasedServiceReferenceComponentMetadata) {
-            // TODO
-            throw new IllegalStateException("Unsupported component type " + component.getClass());
+            CollectionBasedServiceReferenceComponentMetadata metadata = (CollectionBasedServiceReferenceComponentMetadata) component;
+            CollectionRecipe listenersRecipe = null;
+            if (metadata.getBindingListeners() != null) {
+                listenersRecipe = new CollectionRecipe(ArrayList.class);;
+                for (BindingListenerMetadata listener : (Collection<BindingListenerMetadata>) metadata.getBindingListeners()) {
+                    listenersRecipe.add(createRecipe(listener));
+                }
+            }
+            Recipe comparatorRecipe = null;
+            if (metadata.getComparator() != null) {
+                comparatorRecipe = (Recipe) getValue(metadata.getComparator(), Comparator.class);
+            }
+            CollectionBasedServiceReferenceRecipe recipe = new CollectionBasedServiceReferenceRecipe(
+                                                                       moduleContext,
+                                                                       moduleContext.getSender(),
+                                                                       metadata,
+                                                                       listenersRecipe,
+                                                                       comparatorRecipe);
+            recipe.setName(component.getName());
+            return recipe;
         } else {
             throw new IllegalStateException("Unsupported component type " + component.getClass());
         }
@@ -234,7 +252,7 @@
     }
 
     private Recipe createRecipe(BindingListenerMetadata listener) throws Exception {
-        ObjectRecipe recipe = new ObjectRecipe(ReferenceServiceRecipe.Listener.class);
+        ObjectRecipe recipe = new ObjectRecipe(AbstractServiceReferenceRecipe.Listener.class);
         recipe.allow(Option.PRIVATE_PROPERTIES);
         recipe.setProperty("listener", getValue(listener.getListenerComponent(), null));
         recipe.setProperty("metadata", listener);

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java?rev=767090&r1=767089&r2=767090&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/Parser.java Tue Apr 21 09:46:41 2009
@@ -716,6 +716,8 @@
             } else if (MEMBER_TYPE_SERVICE_REFERENCE.equals(memberType)) {
                 references.setMemberType(CollectionBasedServiceReferenceComponentMetadata.MEMBER_TYPE_SERVICE_REFERENCES);
             }
+        } else {
+            references.setMemberType(CollectionBasedServiceReferenceComponentMetadata.MEMBER_TYPE_SERVICES);
         }
         if (element.hasAttribute(ORDERING_BASIS_ATTRIBUTE)) {
             String ordering = element.getAttribute(ORDERING_BASIS_ATTRIBUTE);

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=767090&r1=767089&r2=767090&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 Tue Apr 21 09:46:41 2009
@@ -27,6 +27,7 @@
 import java.util.Set;
 
 import org.apache.geronimo.blueprint.BlueprintConstants;
+import org.apache.geronimo.blueprint.utils.ReflectionUtils;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceUnregisteredException.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceUnregisteredException.java?rev=767090&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceUnregisteredException.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ServiceUnregisteredException.java Tue Apr 21 09:46:41 2009
@@ -0,0 +1,11 @@
+package org.apache.geronimo.blueprint.context;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: gnodet
+ * Date: Apr 20, 2009
+ * Time: 3:53:19 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ServiceUnregisteredException extends RuntimeException {
+}

Copied: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/UnaryServiceReferenceRecipe.java (from r766654, geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReferenceServiceRecipe.java)
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/UnaryServiceReferenceRecipe.java?p2=geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/UnaryServiceReferenceRecipe.java&p1=geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReferenceServiceRecipe.java&r1=766654&r2=767090&rev=767090&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReferenceServiceRecipe.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/UnaryServiceReferenceRecipe.java Tue Apr 21 09:46:41 2009
@@ -19,39 +19,23 @@
 package org.apache.geronimo.blueprint.context;
 
 import java.lang.reflect.Type;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Set;
-import java.util.Collection;
-import java.util.Map;
-import java.util.HashMap;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.Set;
 
-import org.apache.xbean.recipe.AbstractRecipe;
+import net.sf.cglib.proxy.Dispatcher;
+import org.apache.geronimo.blueprint.Destroyable;
+import org.apache.geronimo.blueprint.ModuleContextEventSender;
 import org.apache.xbean.recipe.ConstructionException;
-import org.apache.xbean.recipe.Recipe;
-import org.apache.xbean.recipe.CollectionRecipe;
 import org.apache.xbean.recipe.ExecutionContext;
-import org.apache.geronimo.blueprint.LifeCycle;
-import org.apache.geronimo.blueprint.BlueprintConstants;
-import org.apache.geronimo.blueprint.ModuleContextEventSender;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceEvent;
+import org.apache.xbean.recipe.Recipe;
 import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.blueprint.reflect.UnaryServiceReferenceComponentMetadata;
-import org.osgi.service.blueprint.reflect.BindingListenerMetadata;
-import org.osgi.service.blueprint.context.ServiceUnavailableException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.blueprint.context.ModuleContext;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-import net.sf.cglib.proxy.ProxyRefDispatcher;
-import net.sf.cglib.proxy.Enhancer;
-import net.sf.cglib.proxy.Dispatcher;
+import org.osgi.service.blueprint.context.ServiceUnavailableException;
+import org.osgi.service.blueprint.reflect.UnaryServiceReferenceComponentMetadata;
 
 /**
  * A recipe to create an unary OSGi service reference.
@@ -61,62 +45,41 @@
  * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
  * @version $Rev: 760378 $, $Date: 2009-03-31 11:31:38 +0200 (Tue, 31 Mar 2009) $
  */
-public class ReferenceServiceRecipe extends AbstractRecipe implements Dispatcher, LifeCycle, ServiceListener {
+public class UnaryServiceReferenceRecipe extends AbstractServiceReferenceRecipe {
 
-    private final ModuleContext moduleContext;
-    private final ModuleContextEventSender sender;
     private final UnaryServiceReferenceComponentMetadata metadata;
-    private final CollectionRecipe listenersRecipe;
     private Class proxyClass;
-    private String filter;
-    private List<Listener> listeners;
 
     private volatile ServiceReference trackedServiceReference;
     private volatile Object trackedService;
     private final Object monitor = new Object();
 
-    public ReferenceServiceRecipe(ModuleContext moduleContext,
-                                  ModuleContextEventSender sender,
-                                  UnaryServiceReferenceComponentMetadata metadata,
-                                  CollectionRecipe listenersRecipe) {
-        this.moduleContext = moduleContext;
-        this.sender = sender;
+    public UnaryServiceReferenceRecipe(ModuleContext moduleContext,
+                                       ModuleContextEventSender sender,
+                                       UnaryServiceReferenceComponentMetadata metadata,
+                                       Recipe listenersRecipe) {
+        super(moduleContext,  sender, metadata, listenersRecipe);
         this.metadata = metadata;
-        this.listenersRecipe = listenersRecipe;
     }
 
     protected Object internalCreate(Type expectedType, boolean lazyRefAllowed) throws ConstructionException {
         // TODO: serviceAvailabilitySpecification
         try {
-            ClassLoader classLoader = new BundleDelegatingClassLoader(moduleContext.getBundleContext().getBundle(),
-                                                                      getClass().getClassLoader());
-            Enhancer e = new Enhancer();
-            e.setClassLoader(classLoader);
-            e.setSuperclass(getTargetClass(classLoader));
-            e.setInterfaces(getInterfaces(classLoader));
-            e.setInterceptDuringConstruction(false);
-            e.setCallback(this);
-            e.setUseFactory(false);
-            Object obj = e.create();
+            // Create the proxy
+            Object obj = createProxy(new ServiceDispatcher(), metadata.getInterfaceNames());
             proxyClass = obj.getClass();
-
-            if (listenersRecipe != null) {
-                listeners = (List<Listener>) listenersRecipe.create(classLoader);
-                for (Listener listener : listeners) {
-                    listener.init(proxyClass);
-                }
-            } else {
-                listeners = Collections.emptyList();
-            }
-
-            filter = getOsgiFilter();
-            moduleContext.getBundleContext().addServiceListener(this, filter);
-            retrack();
-
+            // Create the listeners and initialize them
+            createListeners();
+            // Add the created proxy to the context
             if (getName() != null) {
                 ExecutionContext.getContext().addObject(getName(), obj);
             }
 
+            // Start tracking the service
+            moduleContext.getBundleContext().addServiceListener(this, getOsgiFilter());
+            retrack();
+
+            // Return the object
             return obj;
         } catch (Throwable t) {
             t.printStackTrace();
@@ -124,148 +87,25 @@
         }
     }
 
-    private String getOsgiFilter() {
-        List<String> members = new ArrayList<String>();
-        // Handle filter
-        String filter = metadata.getFilter();
-        if (filter != null && filter.length() > 0) {
-            if (!filter.startsWith("(")) {
-                filter = "(" + filter + ")";
-            }
-            members.add(filter);
-        }
-        // Handle interfaces
-        Set<String> interfaces = (Set<String>) metadata.getInterfaceNames();
-        if (interfaces != null && !interfaces.isEmpty()) {
-            for (String itf : interfaces) {
-                members.add("(" + Constants.OBJECTCLASS + "=" + itf + ")");
-            }
-        }
-        // Handle component name
-        String componentName = metadata.getComponentName();
-        if (componentName != null && componentName.length() > 0) {
-            members.add("(" + BlueprintConstants.COMPONENT_NAME_PROPERTY + "=" + componentName + ")");
-        }
-        // Create filter
-        if (members.isEmpty()) {
-            throw new IllegalStateException("No constraints were specified on the service reference");
-        }
-        StringBuilder sb = new StringBuilder("(&");
-        for (String member : members) {
-            sb.append(member);
-        }
-        sb.append(")");
-        return sb.toString();
-    }
-
-    private Class[] getInterfaces(ClassLoader classLoader) throws ClassNotFoundException {
-        List<Class> interfaces = new ArrayList<Class>();
-        for (String name : (Set<String>) metadata.getInterfaceNames()) {
-            Class clazz = classLoader.loadClass(name);
-            if (clazz.isInterface()) {
-                interfaces.add(clazz);
-            }
-        }
-        return interfaces.toArray(new Class[interfaces.size()]);
-    }
-
-    private Class getTargetClass(ClassLoader classLoader) throws ClassNotFoundException {
-        Class root = Object.class;
-        for (String name : (Set<String>) metadata.getInterfaceNames()) {
-            Class clazz = classLoader.loadClass(name);
-            if (!clazz.isInterface()) {
-                if (root == Object.class) {
-                    root = clazz;
-                    continue;
-                }
-                // Check that all classes are in the same hierarchy
-                for (Class p = clazz; p != Object.class; p = p.getSuperclass()) {
-                    if (p == root) {
-                        root = clazz;
-                        continue;
-                    }
-                }
-                for (Class p = root; p != Object.class; p = p.getSuperclass()) {
-                    if (p == clazz) {
-                        continue;
-                    }
-                }
-                throw new ConstructionException("Classes " + root.getClass().getName() + " and " + clazz.getName() + " are not in the same hierarchy");
-            }
-        }
-        return root;
-    }
-
     public boolean canCreate(Type type) {
         return true;
     }
 
-    public Object loadObject() throws Exception {
-        Object svc = trackedService;
-        if (svc == null && metadata.getTimeout() > 0) {
-            Set<String> interfaces = (Set<String>) metadata.getInterfaceNames();
-            sender.sendWaiting(moduleContext, interfaces.toArray(new String[interfaces.size()]), filter);
-            synchronized (monitor) {
-                monitor.wait(metadata.getTimeout());
-            }
-            svc = trackedService;
-        }
-        if (svc == null) {
-            throw new ServiceUnavailableException("Timeout expired when waiting for OSGi service", proxyClass.getSuperclass(), filter);
-        }
-        return svc;
-    }
-
-    public void init() throws Exception {
-    }
-
     public void destroy() throws Exception {
         moduleContext.getBundleContext().removeServiceListener(this);
+        unbind();
     }
 
     private ServiceReference getBestServiceReference(ServiceReference[] references) {
-        int length = (references == null) ? 0 : references.length;
-        if (length == 0) { /* if no service is being tracked */
+        if (references == null || references.length == 0) {
             return null;
         }
-        int index = 0;
-        if (length > 1) { /* if more than one service, select highest ranking */
-            int rankings[] = new int[length];
-            int count = 0;
-            int maxRanking = Integer.MIN_VALUE;
-            for (int i = 0; i < length; i++) {
-                Object property = references[i].getProperty(Constants.SERVICE_RANKING);
-                int ranking = (property instanceof Integer) ? ((Integer) property).intValue() : 0;
-                rankings[i] = ranking;
-                if (ranking > maxRanking) {
-                    index = i;
-                    maxRanking = ranking;
-                    count = 1;
-                } else {
-                    if (ranking == maxRanking) {
-                        count++;
-                    }
-                }
-            }
-            if (count > 1) { /* if still more than one service, select lowest id */
-                long minId = Long.MAX_VALUE;
-                for (int i = 0; i < length; i++) {
-                    if (rankings[i] == maxRanking) {
-                        long id = ((Long) (references[i].getProperty(Constants.SERVICE_ID))).longValue();
-                        if (id < minId) {
-                            index = i;
-                            minId = id;
-                        }
-                    }
-                }
-            }
-        }
-        return references[index];
+        return Collections.max(Arrays.asList(references));
     }
 
     private void retrack() {
         try {
-            ServiceReference[] refs = moduleContext.getBundleContext().getServiceReferences(null, filter);
+            ServiceReference[] refs = moduleContext.getBundleContext().getServiceReferences(null, getOsgiFilter());
             ServiceReference ref = getBestServiceReference(refs);
             if (ref != null) {
                 bind(ref);
@@ -277,27 +117,21 @@
         }
     }
 
-    private void track(ServiceReference ref) {
+    protected void track(ServiceReference ref) {
         if (trackedServiceReference == null) {
             bind(ref);
         } else {
-            Object property = trackedServiceReference.getProperty(Constants.SERVICE_RANKING);
-            int trackedRanking = (property instanceof Integer) ? ((Integer) property).intValue() : 0;
-            property = ref.getProperty(Constants.SERVICE_RANKING);
-            int newRanking = (property instanceof Integer) ? ((Integer) property).intValue() : 0;
-            if (trackedRanking > newRanking) {
+            if (trackedServiceReference.compareTo(ref) > 0) {
                 return;
-            } else if (trackedRanking == newRanking) {
-                long trackedId = ((Long) (trackedServiceReference.getProperty(Constants.SERVICE_ID))).longValue();
-                long newId = ((Long) (ref.getProperty(Constants.SERVICE_ID))).longValue();
-                if (trackedId < newId) {
-                    return;
-                }
             }
             bind(ref);
         }
     }
 
+    protected void untrack(ServiceReference ref) {
+        retrack();
+    }
+
     private void bind(ServiceReference ref) {
         synchronized (monitor) {
             if (trackedServiceReference != null) {
@@ -324,82 +158,24 @@
         }
     }
 
-    public void serviceChanged(ServiceEvent event) {
-        int eventType = event.getType();
-        ServiceReference ref = event.getServiceReference();
-        switch (eventType) {
-            case ServiceEvent.REGISTERED:
-            case ServiceEvent.MODIFIED:
-                track(ref);
-                break;
-            case ServiceEvent.UNREGISTERING:
-                retrack();
-                break;
-        }
-    }
-
-    public static class Listener {
+    public class ServiceDispatcher implements Dispatcher {
 
-        private Object listener;
-        private BindingListenerMetadata metadata;
-        private List<Method> bindMethodsOneArg;
-        private List<Method> bindMethodsTwoArgs;
-        private List<Method> unbindMethodsOneArg;
-        private List<Method> unbindMethodsTwoArgs;
-
-        public void init(Class proxyClass) {
-            Class listenerClass = listener.getClass();
-            Class[] oneArgParams = new Class[] { ServiceReference.class };
-            Class[] twoArgsParams = new Class[] { proxyClass, Map.class };
-            String bindName = metadata.getBindMethodName();
-            if (bindName != null) {
-                bindMethodsOneArg = ReflectionUtils.findCompatibleMethods(listenerClass, bindName, oneArgParams);
-                bindMethodsTwoArgs = ReflectionUtils.findCompatibleMethods(listenerClass, bindName, twoArgsParams);
-            } else {
-                bindMethodsOneArg = Collections.emptyList();
-                bindMethodsTwoArgs = Collections.emptyList();
-            }
-            String unbindName = metadata.getUnbindMethodName();
-            if (unbindName != null) {
-                unbindMethodsOneArg = ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, oneArgParams);
-                unbindMethodsTwoArgs = ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, twoArgsParams);
-            } else {
-                unbindMethodsOneArg = Collections.emptyList();
-                unbindMethodsTwoArgs = Collections.emptyList();
-            }
-        }
-
-        public void bind(ServiceReference reference, Object service) {
-            invokeMethods(bindMethodsOneArg, bindMethodsTwoArgs, reference, service);
-        }
-
-        public void unbind(ServiceReference reference, Object service) {
-            invokeMethods(unbindMethodsOneArg, unbindMethodsTwoArgs, reference, service);
-        }
-
-        private void invokeMethods(List<Method> oneArgMethods, List<Method> twoArgsMethods, ServiceReference reference, Object service) {
-            for (Method method : oneArgMethods) {
-                try {
-                    method.invoke(listener, reference);
-                } catch (Exception e) {
-                    e.printStackTrace(); // TODO: log
+        public Object loadObject() throws Exception {
+            Object svc = trackedService;
+            if (svc == null && metadata.getTimeout() > 0) {
+                Set<String> interfaces = (Set<String>) metadata.getInterfaceNames();
+                sender.sendWaiting(moduleContext, interfaces.toArray(new String[interfaces.size()]), getOsgiFilter());
+                synchronized (monitor) {
+                    monitor.wait(metadata.getTimeout());
                 }
+                svc = trackedService;
             }
-            Map<String, Object> props = null;
-            for (Method method : twoArgsMethods) {
-                if (props == null) {
-                    props = new HashMap<String, Object>();
-                    for (String name : reference.getPropertyKeys()) {
-                        props.put(name, reference.getProperty(name));
-                    }
-                }
-                try {
-                    method.invoke(listener, service, props);
-                } catch (Exception e) {
-                    e.printStackTrace(); // TODO: log
-                }
+            if (svc == null) {
+                throw new ServiceUnavailableException("Timeout expired when waiting for OSGi service", proxyClass.getSuperclass(), getOsgiFilter());
             }
+            return svc;
         }
 
     }
+
 }

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicCollection.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicCollection.java?rev=767090&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicCollection.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicCollection.java Tue Apr 21 09:46:41 2009
@@ -0,0 +1,263 @@
+/*
+ * 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.utils;
+
+import java.lang.ref.WeakReference;
+import java.util.AbstractCollection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Collection that allows iterators to see addition or removals of elements while iterating.
+ * This collection and its iterators are thread safe but all operations happen under a
+ * synchronization lock, so the performance in heavy concurrency load is far from optimal.
+ * If such a use is needed, a CopyOnWriteArrayList may be more suited.
+ *
+ * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
+ * @version $Rev: 766653 $, $Date: 2009-04-20 13:19:48 +0200 (Mon, 20 Apr 2009) $
+ */
+public class DynamicCollection<E> extends AbstractCollection<E> {
+
+    protected final Object lock = new Object();
+    protected final List<E> storage;
+    protected final List<WeakReference<DynamicIterator>> iterators;
+
+    public DynamicCollection() {
+        this.storage = new ArrayList<E>();
+        this.iterators = new ArrayList<WeakReference<DynamicIterator>>();
+    }
+
+    public Iterator<E> iterator() {
+        return iterator(0);
+    }
+
+    public Iterator<E> iterator(int index) {
+        DynamicIterator iterator = createIterator(index);
+        synchronized (lock) {
+            for (Iterator<WeakReference<DynamicIterator>> it = iterators.iterator(); it.hasNext();) {
+                if (it.next().get() == null) {
+                    it.remove();
+                }
+            }
+            iterators.add(new WeakReference<DynamicIterator>(iterator));
+        }
+        return iterator;
+    }
+
+    protected DynamicIterator createIterator(int index) {
+        return new DynamicIterator(index);
+    }
+
+    public int size() {
+        synchronized (lock) {
+            return storage.size();
+        }
+    }
+
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    public boolean contains(Object o) {
+        if (o == null) {
+            throw new NullPointerException();
+        }
+        synchronized (lock) {
+            return storage.contains(o);
+        }
+    }
+
+    public Object[] toArray() {
+        synchronized (lock) {
+            return storage.toArray();
+        }
+    }
+
+    public <T> T[] toArray(T[] a) {
+        synchronized (lock) {
+            return storage.toArray(a);
+        }
+    }
+
+    public boolean containsAll(Collection<?> c) {
+        synchronized (lock) {
+            return storage.containsAll(c);
+        }
+    }
+
+    public boolean add(E o) {
+        if (o == null) {
+            throw new NullPointerException();
+        }
+        synchronized (lock) {
+            return storage.add(o);
+        }
+    }
+
+    public boolean remove(Object o) {
+        if (o == null) {
+            throw new NullPointerException();
+        }
+        synchronized (lock) {
+            int index = storage.indexOf(o);
+            return remove(index) != null;
+        }
+    }
+
+    public void add(int index, E o) {
+        if (o == null) {
+            throw new NullPointerException();
+        }
+        synchronized (lock) {
+            storage.add(index, o);
+            for (Iterator<WeakReference<DynamicIterator>> it = iterators.iterator(); it.hasNext();) {
+                DynamicIterator i = it.next().get();
+                if (i == null) {
+                    it.remove();
+                } else {
+                    i.addedIndex(index);
+                }
+            }
+        }
+    }
+
+    public E remove(int index) {
+        synchronized (lock) {
+            E o = storage.remove(index);
+            for (Iterator<WeakReference<DynamicIterator>> it = iterators.iterator(); it.hasNext();) {
+                WeakReference<DynamicIterator> r = it.next();
+                DynamicIterator i = r.get();
+                if (i == null) {
+                    it.remove();
+                } else {
+                    i.removedIndex(index);
+                }
+            }
+            return o;
+        }
+    }
+
+    public class DynamicIterator implements Iterator<E> {
+
+        protected int index;
+        protected boolean hasNextCalled;
+        protected E next;
+        protected boolean hasPreviousCalled;
+        protected E previous;
+        protected E last;
+
+        public DynamicIterator() {
+            this(0);
+        }
+
+        public DynamicIterator(int index) {
+            this.index = index;
+        }
+
+        protected synchronized void removedIndex(int index) {
+            if (index < this.index || (index == this.index && (hasNextCalled || hasPreviousCalled))) {
+                this.index--;
+            }
+        }
+
+        protected synchronized void addedIndex(int index) {
+            if (index < this.index || (index == this.index && (hasNextCalled || hasPreviousCalled))) {
+                this.index++;
+            }
+        }
+
+        public synchronized boolean hasNext() {
+            synchronized (lock) {
+                hasPreviousCalled = false;
+                hasNextCalled = true;
+                next = index < storage.size() ? storage.get(index) : null;
+                return next != null;
+            }
+        }
+
+        public synchronized boolean hasPrevious() {
+            synchronized (lock) {
+                hasPreviousCalled = true;
+                hasNextCalled = false;
+                previous = index > 0 ? storage.get(index - 1) : null;
+                return previous != null;
+            }
+        }
+
+        public synchronized E next() {
+            try {
+                if (!hasNextCalled) {
+                    hasNext();
+                }
+                last = next;
+                if (next != null) {
+                    ++index;
+                    return next;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            } finally {
+                hasPreviousCalled = false;
+                hasNextCalled = false;
+            }
+        }
+
+        public synchronized E previous() {
+            try {
+                if (!hasPreviousCalled) {
+                    hasPrevious();
+                }
+                last = previous;
+                if (previous != null) {
+                    --index;
+                    return previous;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            } finally {
+                hasPreviousCalled = false;
+                hasNextCalled = false;
+            }
+        }
+
+        public synchronized int nextIndex() {
+            return index;
+        }
+
+        public synchronized int previousIndex() {
+            return index - 1;
+        }
+
+        public synchronized void remove() {
+            if (last == null) {
+                throw new IllegalStateException();
+            }
+            synchronized (lock) {
+                if (storage.get(index - 1) == last) {
+                    storage.remove(index - 1);
+                }
+            }
+            last = null;
+
+        }
+    }
+}

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicList.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicList.java?rev=767090&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicList.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicList.java Tue Apr 21 09:46:41 2009
@@ -0,0 +1,115 @@
+/*
+ * 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.utils;
+
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Iterator;
+import java.util.Collection;
+import java.util.RandomAccess;
+import java.lang.ref.WeakReference;
+
+/**
+ * Same as DynamicCollection but implementing the List interface.
+ * All list method implemetations are actually provided by the DynamicCollection class
+ * itself as it already relies on a List storage.
+ *
+ * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
+ * @version $Rev: 766653 $, $Date: 2009-04-20 13:19:48 +0200 (Mon, 20 Apr 2009) $
+ */
+public class DynamicList<E> extends DynamicCollection<E> implements List<E>, RandomAccess {
+
+    public ListIterator<E> listIterator() {
+        return listIterator(0);
+    }
+
+    public ListIterator<E> listIterator(int index) {
+        return (ListIterator<E>) iterator(index);
+    }
+
+    @Override
+    protected DynamicIterator createIterator(int index) {
+        return new DynamicListIterator(index);
+    }
+
+    public E get(int index) {
+        synchronized (lock) {
+            return storage.get(index);
+        }
+    }
+
+    public E set(int index, E o) {
+        if (o == null) {
+            throw new NullPointerException();
+        }
+        synchronized (lock) {
+            return storage.set(index, o);
+        }
+    }
+
+    public int indexOf(Object o) {
+        if (o == null) {
+            throw new NullPointerException();
+        }
+        synchronized (lock) {
+            return storage.indexOf(o);
+        }
+    }
+
+    public int lastIndexOf(Object o) {
+        if (o == null) {
+            throw new NullPointerException();
+        }
+        synchronized (lock) {
+            return storage.lastIndexOf(o);
+        }
+    }
+
+    public boolean addAll(int index, Collection<? extends E> c) {
+        synchronized (lock) {
+            boolean modified = false;
+            Iterator<? extends E> e = c.iterator();
+            while (e.hasNext()) {
+                add(index++, e.next());
+                modified = true;
+            }
+            return modified;
+        }
+    }
+
+    public List<E> subList(int fromIndex, int toIndex) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    protected class DynamicListIterator extends DynamicIterator implements ListIterator<E> {
+
+        public DynamicListIterator(int index) {
+            super(index);
+        }
+
+        public synchronized void set(E o) {
+            DynamicList.this.set(index, o);
+        }
+
+        public synchronized void add(E o) {
+            DynamicList.this.add(index++, o);
+        }
+
+    }
+}

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSet.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSet.java?rev=767090&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSet.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSet.java Tue Apr 21 09:46:41 2009
@@ -0,0 +1,48 @@
+/*
+ * 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.utils;
+
+import java.util.Set;
+import java.util.Iterator;
+import java.lang.ref.WeakReference;
+
+/**
+ * Same as DynamicCollection but implementing the Set interface, thus not allowing
+ * duplicates.
+ * Note that the insertion performance of this set is not very good due to the underlying
+ * storage as a list which enforce a full traversal of the storage before adding any element. 
+ *
+ * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
+ * @version $Rev: 766653 $, $Date: 2009-04-20 13:19:48 +0200 (Mon, 20 Apr 2009) $
+ */
+public class DynamicSet<E> extends DynamicCollection<E> implements Set<E> {
+
+    @Override
+    public boolean add(E o) {
+        synchronized (lock) {
+            if (!storage.contains(o)) {
+                storage.add(o);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+}

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedList.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedList.java?rev=767090&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedList.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedList.java Tue Apr 21 09:46:41 2009
@@ -0,0 +1,74 @@
+/*
+ * 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.utils;
+
+import java.util.Comparator;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ *
+ *
+ * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
+ * @version $Rev: 766653 $, $Date: 2009-04-20 13:19:48 +0200 (Mon, 20 Apr 2009) $
+ */
+public class DynamicSortedList<E> extends DynamicList<E> {
+
+    protected Comparator<E> comparator;
+
+    public DynamicSortedList() {
+    }
+
+    public DynamicSortedList(Comparator<E> comparator) {
+        this.comparator = comparator;
+    }
+
+    @Override
+    public boolean add(E o) {
+        if (o == null) {
+            throw new NullPointerException();
+        }
+        if (comparator == null && !(o instanceof Comparable)) {
+            throw new IllegalArgumentException("Elements in this sorted list must implement the " + Comparable.class.getName() + " interface");
+        }
+        synchronized (lock) {
+            int index = Collections.binarySearch(storage, o, comparator);
+            if (index < 0) {
+                index = -index - 1;
+            } else {
+                index = index + 1;
+            }
+            super.add(index, o);
+            return true;
+        }
+    }
+
+    public void add(int index, Object o) {
+        throw new UnsupportedOperationException("Insertion at a given position is not allowed on a sorted list");
+    }
+
+    public boolean addAll(int index, Collection c) {
+        throw new UnsupportedOperationException("Insertion at a given position is not allowed on a sorted list");
+    }
+
+    public Object set(int index, Object o) {
+        throw new UnsupportedOperationException("Insertion at a given position is not allowed on a sorted list");
+    }
+
+}

Added: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedSet.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedSet.java?rev=767090&view=auto
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedSet.java (added)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/DynamicSortedSet.java Tue Apr 21 09:46:41 2009
@@ -0,0 +1,103 @@
+/*
+ * 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.utils;
+
+import java.util.Comparator;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.NoSuchElementException;
+
+/**
+ *
+ *
+ * @author <a href="mailto:dev@geronimo.apache.org">Apache Geronimo Project</a>
+ * @version $Rev: 766653 $, $Date: 2009-04-20 13:19:48 +0200 (Mon, 20 Apr 2009) $
+ */
+public class DynamicSortedSet<E> extends DynamicSet<E> implements SortedSet<E> {
+
+    protected Comparator<? super E> comparator;
+
+    public DynamicSortedSet() {
+    }
+
+    public DynamicSortedSet(Comparator<? super E> comparator) {
+        this.comparator = comparator;
+    }
+
+    @Override
+    public boolean add(E o) {
+        if (o == null) {
+            throw new NullPointerException();
+        }
+        if (comparator == null && !(o instanceof Comparable)) {
+            throw new IllegalArgumentException("Elements in this sorted list must implement the " + Comparable.class.getName() + " interface");
+        }
+        synchronized (lock) {
+            int index = Collections.binarySearch(storage, o, comparator);
+            if (index < 0) {
+                super.add(-index - 1, o);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public Comparator<? super E> comparator() {
+        return comparator;
+    }
+
+    public SortedSet<E> subSet(E fromElement, E toElement) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    public SortedSet<E> headSet(E toElement) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    public SortedSet<E> tailSet(E fromElement) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    public E first() {
+        synchronized (lock) {
+            if (storage.isEmpty()) {
+                throw new NoSuchElementException();
+            } else {
+                return storage.get(0);
+            }
+        }
+    }
+
+    public E last() {
+        synchronized (lock) {
+            if (storage.isEmpty()) {
+                throw new NoSuchElementException();
+            } else {
+                return storage.get(storage.size() - 1);
+            }
+        }
+    }
+
+    @Override
+    public void add(int index, E o) {
+        throw new UnsupportedOperationException("Insertion at a given position is not allowed on a sorted list");
+    }
+}
\ No newline at end of file

Copied: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/ReflectionUtils.java (from r766654, geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReflectionUtils.java)
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/ReflectionUtils.java?p2=geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/ReflectionUtils.java&p1=geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReflectionUtils.java&r1=766654&r2=767090&rev=767090&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/context/ReflectionUtils.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/utils/ReflectionUtils.java Tue Apr 21 09:46:41 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.geronimo.blueprint.context;
+package org.apache.geronimo.blueprint.utils;
 
 import java.lang.reflect.Method;
 import java.util.Set;

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

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

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



Mime
View raw message