You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ui...@apache.org on 2012/02/24 11:47:51 UTC

svn commit: r1293173 [2/8] - in /felix/sandbox/uiterlix/dependencymanager/core: ./ .externalToolBuilders/ .settings/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/felix/ src/main/java/org/apache/fel...

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,585 @@
+/*
+ * 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.felix.dm;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.felix.dm.impl.AdapterServiceImpl;
+import org.apache.felix.dm.impl.AspectServiceImpl;
+import org.apache.felix.dm.impl.BundleAdapterServiceImpl;
+import org.apache.felix.dm.impl.ComponentImpl;
+import org.apache.felix.dm.impl.FactoryConfigurationAdapterServiceImpl;
+import org.apache.felix.dm.impl.Logger;
+import org.apache.felix.dm.impl.ResourceAdapterServiceImpl;
+import org.apache.felix.dm.impl.dependencies.BundleDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.ConfigurationDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.ResourceDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.ServiceDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.TemporalServiceDependencyImpl;
+import org.apache.felix.dm.impl.index.AspectFilterIndex;
+import org.apache.felix.dm.impl.index.MultiPropertyExactFilter;
+import org.apache.felix.dm.impl.index.ServiceRegistryCache;
+import org.apache.felix.dm.impl.metatype.PropertyMetaDataImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * The dependency manager manages all components and their dependencies. Using 
+ * this API you can declare all components and their dependencies. Under normal
+ * circumstances, you get passed an instance of this class through the
+ * <code>DependencyActivatorBase</code> subclass you use as your
+ * <code>BundleActivator</code>, but it is also possible to create your
+ * own instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DependencyManager {
+    public static final String ASPECT = "org.apache.felix.dependencymanager.aspect";
+    public static final String SERVICEREGISTRY_CACHE_INDICES = "org.apache.felix.dependencymanager.filterindex";
+    public static final String METHOD_CACHE_SIZE = "org.apache.felix.dependencymanager.methodcache";
+    private final BundleContext m_context;
+    private final Logger m_logger;
+    private List m_components = Collections.synchronizedList(new ArrayList());
+
+    /**
+     * Creates a new dependency manager. You need to supply the
+     * <code>BundleContext</code> to be used by the dependency
+     * manager to register services and communicate with the 
+     * framework.
+     * 
+     * @param context the bundle context
+     */
+    public DependencyManager(BundleContext context) {
+        this(context, new Logger(context));
+    }
+    
+    DependencyManager(BundleContext context, Logger logger) {
+        m_context = createContext(context);
+        m_logger = logger;
+        synchronized (m_dependencyManagers) {
+            m_dependencyManagers.add(new WeakReference(this));
+        }
+    }
+
+    // service registry cache
+    private static ServiceRegistryCache m_serviceRegistryCache;
+    private static final Set /* WeakReference<DependencyManager> */ m_dependencyManagers = new HashSet();
+    static {
+        String index = System.getProperty(SERVICEREGISTRY_CACHE_INDICES);
+        if (index != null) {
+            Bundle bundle = FrameworkUtil.getBundle(DependencyManager.class);
+            try {
+                if (bundle.getState() != Bundle.ACTIVE) {
+                    bundle.start();
+                }
+                BundleContext bundleContext = bundle.getBundleContext();
+                
+                m_serviceRegistryCache = new ServiceRegistryCache(bundleContext);
+                m_serviceRegistryCache.open(); // TODO close it somewhere
+                String[] props = index.split(";");
+                for (int i = 0; i < props.length; i++) {
+                    if (props[i].equals("*aspect*")) {
+                        m_serviceRegistryCache.addFilterIndex(new AspectFilterIndex());
+                    }
+                    else {
+                        String[] propList = props[i].split(",");
+                        m_serviceRegistryCache.addFilterIndex(new MultiPropertyExactFilter(propList));
+                    }
+                }
+            }
+            catch (BundleException e) {
+                // if we cannot start ourselves, we cannot use the indices
+                // TODO we might want to warn people about this
+            }
+        }
+    }
+    
+    public static List getDependencyManagers() {
+        List /* DependencyManager */ result = new ArrayList();
+        synchronized (m_dependencyManagers) {
+            Iterator iterator = m_dependencyManagers.iterator();
+            while (iterator.hasNext()) {
+                WeakReference reference = (WeakReference) iterator.next();
+                DependencyManager manager = (DependencyManager) reference.get();
+                if (manager != null) {
+                    try {
+                        manager.getBundleContext().getBundle();
+                        result.add(manager);
+                        continue;
+                    }
+                    catch (IllegalStateException e) {
+                    }
+                }
+                iterator.remove();
+            }
+        }
+        return result;
+    }
+    
+    private BundleContext createContext(BundleContext context) {
+        if (m_serviceRegistryCache != null) {
+//            System.out.println("DM: Enabling bundle context interceptor for bundle #" + context.getBundle().getBundleId());
+            return m_serviceRegistryCache.createBundleContextInterceptor(context);
+        }
+        else {
+            return context;
+        }
+    }
+    
+    public BundleContext getBundleContext() {
+        return m_context;
+    }
+
+    /**
+     * Adds a new service to the dependency manager. After the service was added
+     * it will be started immediately.
+     * 
+     * @param service the service to add
+     */
+    public void add(Component service) {
+        m_components.add(service);
+        service.start();
+    }
+
+    /**
+     * Removes a service from the dependency manager. Before the service is removed
+     * it is stopped first.
+     * 
+     * @param service the service to remove
+     */
+    public void remove(Component service) {
+        service.stop();
+        m_components.remove(service);
+    }
+
+    /**
+     * Creates a new service.
+     * 
+     * @return the new service
+     */
+    public Component createComponent() {
+        return new ComponentImpl(m_context, this, m_logger);
+    }
+    
+    /**
+     * Creates a new service dependency.
+     * 
+     * @return the service dependency
+     */
+    public ServiceDependency createServiceDependency() {
+        return new ServiceDependencyImpl(m_context, m_logger);
+    }
+    
+    /**
+     * Creates a new temporal service dependency.
+     * 
+     * @return a new temporal service dependency
+     */
+    public TemporalServiceDependency createTemporalServiceDependency() {
+        return new TemporalServiceDependencyImpl(m_context, m_logger);
+    }
+
+    /**
+     * Creates a new configuration dependency.
+     * 
+     * @return the configuration dependency
+     */
+    public ConfigurationDependency createConfigurationDependency() {
+        return new ConfigurationDependencyImpl(m_context, m_logger);
+    }
+    
+    /**
+     * Creates a new configuration property metadata.
+     * 
+     * @return the configuration property metadata.
+     */
+    public PropertyMetaData createPropertyMetaData() {
+        return new PropertyMetaDataImpl();
+    }
+
+    /**
+     * Creates a new bundle dependency.
+     * 
+     * @return a new BundleDependency instance.
+     */
+    public BundleDependency createBundleDependency() {
+        return new BundleDependencyImpl(m_context, m_logger);
+    }
+    
+    /**
+     * Creates a new resource dependency.
+     * 
+     * @return the resource dependency
+     */
+    public ResourceDependency createResourceDependency() {
+        return new ResourceDependencyImpl(m_context, m_logger);
+    }
+
+    /**
+     * Creates a new aspect. The aspect will be applied to any service that
+     * matches the specified interface and filter. For each matching service
+     * an aspect will be created based on the aspect implementation class.
+     * The aspect will be registered with the same interface and properties
+     * as the original service, plus any extra properties you supply here.
+     * It will also inherit all dependencies, and if you declare the original
+     * service as a member it will be injected.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_service")
+     *     .setImplementation(ExistingServiceAspect.class)
+     * );
+     * </pre></blockquote>
+     * 
+     * @param serviceInterface the service interface to apply the aspect to
+     * @param serviceFilter the filter condition to use with the service interface
+     * @param ranking the level used to organize the aspect chain ordering
+     * @param autoConfig the aspect implementation field name where to inject original service. 
+     *     If null, any field matching the original service will be injected.
+     * @return a service that acts as a factory for generating aspects
+     */
+    public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String autoConfig) {
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null);
+    }
+    /**
+     * Creates a new aspect. The aspect will be applied to any service that
+     * matches the specified interface and filter. For each matching service
+     * an aspect will be created based on the aspect implementation class.
+     * The aspect will be registered with the same interface and properties
+     * as the original service, plus any extra properties you supply here.
+     * It will also inherit all dependencies, and if you declare the original
+     * service as a member it will be injected.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     * manager.createAspectService(ExistingService.class, "(foo=bar)", 10)
+     *     .setImplementation(ExistingServiceAspect.class)
+     * );
+     * </pre></blockquote>
+     * 
+     * @param serviceInterface the service interface to apply the aspect to
+     * @param serviceFilter the filter condition to use with the service interface
+     * @param ranking the level used to organize the aspect chain ordering
+     * @return a service that acts as a factory for generating aspects
+     */
+    public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking) {
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null);
+    }
+    /**
+     * Creates a new aspect. The aspect will be applied to any service that
+     * matches the specified interface and filter. For each matching service
+     * an aspect will be created based on the aspect implementation class.
+     * The aspect will be registered with the same interface and properties
+     * as the original service, plus any extra properties you supply here.
+     * It will also inherit all dependencies, and if you declare the original
+     * service as a member it will be injected.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
+     *     .setImplementation(ExistingServiceAspect.class)
+     * );
+     * </pre></blockquote>
+     * 
+     * @param serviceInterface the service interface to apply the aspect to
+     * @param serviceFilter the filter condition to use with the service interface
+     * @param ranking the level used to organize the aspect chain ordering
+     * @param add name of the callback method to invoke on add
+     * @param change name of the callback method to invoke on change
+     * @param remove name of the callback method to invoke on remove
+     * @return a service that acts as a factory for generating aspects
+     */
+    public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove) {
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove);
+    }
+    
+    /**
+     * Creates a new adapter. The adapter will be applied to any service that
+     * matches the specified interface and filter. For each matching service
+     * an adapter will be created based on the adapter implementation class.
+     * The adapter will be registered with the specified interface and existing properties
+     * from the original service plus any extra properties you supply here.
+     * It will also inherit all dependencies, and if you declare the original
+     * service as a member it will be injected.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
+     *     .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+     *     .setImplementation(AdapterImpl.class);
+     * </pre></blockquote>
+     * 
+     * @param serviceInterface the service interface to apply the adapter to
+     * @param serviceFilter the filter condition to use with the service interface
+     * @return a service that acts as a factory for generating adapters
+     */
+    public Component createAdapterService(Class serviceInterface, String serviceFilter) {
+        return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null);
+    }
+    /**
+     * Creates a new adapter. The adapter will be applied to any service that
+     * matches the specified interface and filter. For each matching service
+     * an adapter will be created based on the adapter implementation class.
+     * The adapter will be registered with the specified interface and existing properties
+     * from the original service plus any extra properties you supply here.
+     * It will also inherit all dependencies, and if you declare the original
+     * service as a member it will be injected.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "m_service")
+     *     .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+     *     .setImplementation(AdapterImpl.class);
+     * </pre></blockquote>
+     * 
+     * @param serviceInterface the service interface to apply the adapter to
+     * @param serviceFilter the filter condition to use with the service interface
+     * @param autoConfig the name of the member to inject the service into
+     * @return a service that acts as a factory for generating adapters
+     */
+    public Component createAdapterService(Class serviceInterface, String serviceFilter, String autoConfig) {
+        return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null);
+    }
+    /**
+     * Creates a new adapter. The adapter will be applied to any service that
+     * matches the specified interface and filter. For each matching service
+     * an adapter will be created based on the adapter implementation class.
+     * The adapter will be registered with the specified interface and existing properties
+     * from the original service plus any extra properties you supply here.
+     * It will also inherit all dependencies, and if you declare the original
+     * service as a member it will be injected.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
+     *     .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+     *     .setImplementation(AdapterImpl.class);
+     * </pre></blockquote>
+     * 
+     * @param serviceInterface the service interface to apply the adapter to
+     * @param serviceFilter the filter condition to use with the service interface
+     * @param add name of the callback method to invoke on add
+     * @param change name of the callback method to invoke on change
+     * @param remove name of the callback method to invoke on remove
+     * @param swap name of the callback method to invoke on swap
+     * @return a service that acts as a factory for generating adapters
+     */
+    public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove, String swap) {
+        return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove, swap);
+    }
+    
+    public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove) {
+        return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove);
+    }
+        
+    /**
+     * Creates a new resource adapter. The adapter will be applied to any resource that
+     * matches the specified filter condition. For each matching resource
+     * an adapter will be created based on the adapter implementation class.
+     * The adapter will be registered with the specified interface and existing properties
+     * from the original resource plus any extra properties you supply here.
+     * It will also inherit all dependencies, and if you declare the original
+     * service as a member it will be injected.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     *  manager.createResourceAdapterService("(&(path=/test)(repository=TestRepository))", true)
+     *         // The interface to use when registering adapter
+     *         .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+     *         // the implementation of the adapter
+     *         .setImplementation(AdapterServiceImpl.class);
+     * </pre></blockquote>
+     *
+     * @param resourceFilter the filter condition to use with the resource
+     * @param resourcePropertiesFilter the filter condition on the resource properties to use with the resource
+     * @param propagate <code>true</code> if properties from the resource should be propagated to the service
+     * @param callbackInstance 
+     * @param callbackChanged 
+     * @return a service that acts as a factory for generating resource adapters
+     * @see Resource
+     */
+    public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackChanged) {
+        return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, null, callbackChanged);
+    }
+    
+    public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackSet, String callbackChanged) {
+        return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, callbackSet, callbackChanged);
+    }
+    
+    public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
+    	return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, null, callbackChanged);
+    }
+    
+    public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged) {
+        return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, callbackSet, callbackChanged);
+    }
+    
+    /**
+     * Creates a new bundle adapter. The adapter will be applied to any bundle that
+     * matches the specified bundle state mask and filter condition. For each matching
+     * bundle an adapter will be created based on the adapter implementation class.
+     * The adapter will be registered with the specified interface
+     * 
+     * TODO and existing properties from the original resource plus any extra properties you supply here.
+     * It will also inherit all dependencies, and if you declare the original
+     * service as a member it will be injected.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     *  manager.createBundleAdapterService(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE, 
+     *                                     "(Bundle-SymbolicName=org.apache.felix.dependencymanager)",
+     *                                     true)
+     *         // The interface to use when registering adapter
+     *         .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+     *         // the implementation of the adapter
+     *         .setImplementation(AdapterServiceImpl.class);
+     * </pre></blockquote>
+     * 
+     * @param bundleStateMask the bundle state mask to apply
+     * @param bundleFilter the filter to apply to the bundle manifest
+     * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
+     * @return a service that acts as a factory for generating bundle adapters
+     */
+    public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
+        return new BundleAdapterServiceImpl(this, bundleStateMask, bundleFilter, propagate);
+    }
+
+    /**
+     * Creates a new Managed Service Factory Configuration Adapter. For each new Config Admin factory configuration matching
+     * the factoryPid, an adapter will be created based on the adapter implementation class.
+     * The adapter will be registered with the specified interface, and with the specified adapter service properties.
+     * Depending on the <code>propagate</code> parameter, every public factory configuration properties 
+     * (which don't start with ".") will be propagated along with the adapter service properties. 
+     * It will also inherit all dependencies.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     *  manager.createFactoryConfigurationAdapterService("MyFactoryPid",  "update", true)
+     *         // The interface to use when registering adapter
+     *         .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+     *         // the implementation of the adapter
+     *         .setImplementation(AdapterServiceImpl.class);
+     * </pre></blockquote>
+     * 
+     * @param factoryPid the pid matching the factory configuration
+     * @param update the adapter method name that will be notified when the factory configuration is created/updated.
+     * @param propagate true if public factory configuration should be propagated to the adapter service properties
+     * @return a service that acts as a factory for generating the managed service factory configuration adapter
+     */
+    public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate) {
+        return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate);
+    }
+    
+    /**
+     * Creates a new Managed Service Factory Configuration Adapter with meta type support. For each new Config Admin 
+     * factory configuration matching the factoryPid, an adapter will be created based on the adapter implementation 
+     * class. The adapter will be registered with the specified interface, and with the specified adapter service 
+     * properties. Depending on the <code>propagate</code> parameter, every public factory configuration properties 
+     * (which don't start with ".") will be propagated along with the adapter service properties. 
+     * It will also inherit all dependencies.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     *       PropertyMetaData[] propertiesMetaData = new PropertyMetaData[] {
+     *            manager.createPropertyMetaData()
+     *               .setCardinality(Integer.MAX_VALUE)
+     *               .setType(String.class)
+     *               .setHeading("English words")
+     *               .setDescription("Declare here some valid english words")
+     *               .setDefaults(new String[] {"hello", "world"})
+     *               .setId("words")
+     *       };
+     * 
+     *       manager.add(createFactoryConfigurationAdapterService("FactoryPid", 
+     *                                                            "updated",
+     *                                                            true, // propagate CM settings
+     *                                                            "EnglishDictionary",
+     *                                                            "English dictionary configuration properties",
+     *                                                            null,
+     *                                                            propertiesMetaData)
+     *               .setImplementation(Adapter.class));
+     * </pre></blockquote>
+     * 
+     * @param factoryPid the pid matching the factory configuration
+     * @param update the adapter method name that will be notified when the factory configuration is created/updated.
+     * @param propagate true if public factory configuration should be propagated to the adapter service properties
+     * @param heading The label used to display the tab name (or section) where the properties are displayed. 
+     *        Example: "Printer Service"
+     * @param desc A human readable description of the factory PID this configuration is associated with. 
+     *        Example: "Configuration for the PrinterService bundle"
+     * @param localization Points to the basename of the Properties file that can localize the Meta Type informations.
+     *        The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
+     *        be overridden by the manifest Bundle-Localization header (see core specification, in section Localization 
+     *        on page 68). You can specify a specific localization basename file using this parameter 
+     *        (e.g. <code>"person"</code> will match person_du_NL.properties in the root bundle directory).
+     * @param propertiesMetaData Array of MetaData regarding configuration properties
+     * @return a service that acts as a factory for generating the managed service factory configuration adapter
+     */
+    public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, 
+                                                            String heading, String desc, String localization,
+                                                            PropertyMetaData[] propertiesMetaData) 
+    {
+        return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate, m_context, m_logger, 
+                                                          heading, desc, localization, propertiesMetaData);        
+    }
+
+    /**
+     * Returns a list of services.
+     * 
+     * @return a list of services
+     */
+    public List getComponents() {
+        return Collections.unmodifiableList(m_components);
+    }
+
+    /**
+     * Removes all components and their dependencies.
+     */
+    public void clear() {
+        List services = getComponents();
+        for (int i = services.size() - 1; i >= 0; i--) {
+            Component service = (Component) services.get(i);
+            remove(service);
+            // remove any state listeners that are still registered
+            if (service instanceof ComponentImpl) {
+                ComponentImpl si = (ComponentImpl) service;
+                si.removeStateListeners();
+            }
+        }
+    }
+    
+}

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,59 @@
+/*
+ * 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.felix.dm;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface DependencyService {
+    /**
+     * Will be called when the dependency becomes available.
+     * 
+     * @param dependency the dependency
+     */
+    public void dependencyAvailable(Dependency dependency);
+    
+    /**
+     * Will be called when the dependency changes.
+     * 
+     * @param dependency the dependency
+     */
+    public void dependencyUnavailable(Dependency dependency);
+    
+    /**
+     * Will be called when the dependency becomes unavailable.
+     * 
+     * @param dependency the dependency
+     */
+    public void dependencyChanged(Dependency dependency);
+    
+    public Object getService(); // is also defined on the Service interface
+    public void initService(); // was an implementation method TODO we use it in ConfDepImpl but should not (probably)
+    public boolean isRegistered(); // impl method
+    public Object[] getCompositionInstances(); // impl method
+    
+    public boolean isInstantiated();
+    
+    /**
+     * Can be called by the dependency whenever it wants to invoke callback methods.
+     */
+    public void invokeCallbackMethod(Object[] instances, String methodName, Class[][] signatures, Object[][] parameters);
+    
+    public Component getServiceInterface();
+}

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,47 @@
+/*
+ * 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.felix.dm;
+
+import java.util.List;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+
+/**
+ * A filter index is an interface you can implement to create your own, optimized index for specific filter expressions.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface FilterIndex {
+    /** Opens this filter index. */
+    public void open(BundleContext context);
+    /** Closes this filter index. */
+    public void close();
+    /** Determines if the combination of class and filter is applicable for this filter index. */
+    public boolean isApplicable(String clazz, String filter);
+    /** Returns all service references that match the specified class and filter. */
+    public List /* <ServiceReference> */ getAllServiceReferences(String clazz, String filter);
+    /** Invoked whenever a service event occurs. */
+    public void serviceChanged(ServiceEvent event);
+    /** Adds a service listener to this filter index. */
+    public void addServiceListener(ServiceListener listener, String filter);
+    /** Removes a service listener from this filter index. */
+    public void removeServiceListener(ServiceListener listener);
+}

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,173 @@
+/*
+ * 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.felix.dm;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class InvocationUtil {
+    private static final Map /* <Key, Method> */ m_methodCache;
+    static {
+        int size = 2048;
+        try {
+            String value = System.getProperty(DependencyManager.METHOD_CACHE_SIZE);
+            if (value != null) {
+                size = Integer.parseInt(value);
+            }
+        }
+        catch (Exception e) {}
+        m_methodCache = new LRUMap(Math.max(size, 64));
+    }
+    
+    public static Object invokeCallbackMethod(Object instance, String methodName, Class[][] signatures, Object[][] parameters) throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+        Class currentClazz = instance.getClass();
+        while (currentClazz != null) {
+            try {
+                return invokeMethod(instance, currentClazz, methodName, signatures, parameters, false);
+            }
+            catch (NoSuchMethodException nsme) {
+                // ignore
+            }
+            currentClazz = currentClazz.getSuperclass();
+        }
+        throw new NoSuchMethodException(methodName);
+    }
+
+    public static Object invokeMethod(Object object, Class clazz, String name, Class[][] signatures, Object[][] parameters, boolean isSuper) throws NoSuchMethodException, InvocationTargetException, IllegalArgumentException, IllegalAccessException {
+        if (object == null) {
+            throw new IllegalArgumentException("Instance cannot be null");
+        }
+        if (clazz == null) {
+            throw new IllegalArgumentException("Class cannot be null");
+        }
+        
+        // if we're talking to a proxy here, dig one level deeper to expose the
+        // underlying invocation handler (we do the same for injecting instances)
+        if (Proxy.isProxyClass(clazz)) {
+            object = Proxy.getInvocationHandler(object);
+            clazz = object.getClass();
+        }
+        
+        Method m = null;
+        for (int i = 0; i < signatures.length; i++) {
+            Class[] signature = signatures[i];
+            m = getDeclaredMethod(clazz, name, signature, isSuper);
+            if (m != null) {
+                return m.invoke(object, parameters[i]);
+            }
+        }
+        throw new NoSuchMethodException(name);
+    }
+    
+    private static Method getDeclaredMethod(Class clazz, String name, Class[] signature, boolean isSuper) {
+        // first check our cache
+        Key key = new Key(clazz, name, signature);
+        Method m = null;
+        synchronized (m_methodCache) {
+            m = (Method) m_methodCache.get(key);
+            if (m != null) {
+                return m;
+            }
+            else if (m_methodCache.containsKey(key)) {
+                // the key is in our cache, it just happens to have a null value
+                return null;
+            }
+        }
+        // then do a lookup
+        try {
+            m = clazz.getDeclaredMethod(name, signature);
+            if (!(isSuper && Modifier.isPrivate(m.getModifiers()))) {
+                m.setAccessible(true);
+            }
+        }
+        catch (NoSuchMethodException e) {
+            // ignore
+        }
+        synchronized (m_methodCache) {
+            m_methodCache.put(key, m);
+        }
+        return m;
+    }
+    
+    public static class Key {
+        private final Class m_clazz;
+        private final String m_name;
+        private final Class[] m_signature;
+
+        public Key(Class clazz, String name, Class[] signature) {
+            m_clazz = clazz;
+            m_name = name;
+            m_signature = signature;
+        }
+
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((m_clazz == null) ? 0 : m_clazz.hashCode());
+            result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
+            result = prime * result + Arrays.hashCode(m_signature);
+            return result;
+        }
+
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            Key other = (Key) obj;
+            if (m_clazz == null) {
+                if (other.m_clazz != null)
+                    return false;
+            }
+            else if (!m_clazz.equals(other.m_clazz))
+                return false;
+            if (m_name == null) {
+                if (other.m_name != null)
+                    return false;
+            }
+            else if (!m_name.equals(other.m_name))
+                return false;
+            if (!Arrays.equals(m_signature, other.m_signature))
+                return false;
+            return true;
+        }
+    }
+    
+    public static class LRUMap extends LinkedHashMap {
+        private final int m_size;
+        
+        public LRUMap(int size) {
+            m_size = size;
+        }
+        
+        protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
+            return size() > m_size;
+        }
+    }
+}

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,87 @@
+/*
+ * 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.felix.dm;
+
+/**
+ * This interface defines meta data regarding a given configuration property.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface PropertyMetaData {
+    /**
+     * The label used to display the property. Example: "Log Level".
+     * @return The label used to display the property (may be localized)
+     */
+    public PropertyMetaData setHeading(String heading);
+
+    /**
+     * The key of a ConfigurationAdmin property. Example: "printer.logLevel"
+     * @return The Configuration Admin property name
+     */
+    public PropertyMetaData setId(String id);
+
+    /**
+     * Returns the property primitive type. If must be either one of the following types:<p>
+     * <ul>
+     *    <li>String.class</li>
+     *    <li>Long.class</li>
+     *    <li>Integer.class</li>
+     *    <li>Character.class</li>
+     *    <li>Byte.class</li>
+     *    <li>Double.class</li>
+     *    <li>Float.class</li>
+     *    <li>Boolean.class</li>
+     * </ul>
+     */
+    public PropertyMetaData setType(Class type);
+
+    /**
+     * Returns a default for this property. The object must be of the appropriate type as defined by the cardinality and getType(). 
+     * The return type is a list of String  objects that can be converted to the appropriate type. The cardinality of the return 
+     * array must follow the absolute cardinality of this type. E.g. if the cardinality = 0, the array must contain 1 element. 
+     * If the cardinality is 1, it must contain 0 or 1 elements. If it is -5, it must contain from 0 to max 5 elements. Note that 
+     * the special case of a 0 cardinality, meaning a single value, does not allow arrays or vectors of 0 elements. 
+     */
+    public PropertyMetaData setDefaults(String[] defaults);
+
+    /**
+     * Returns the property description. The description may be localized and must describe the semantics of this type and any 
+     * constraints. Example: "Select the log level for the Printer Service".
+     * @return a localizable description of the property.
+     */
+    public PropertyMetaData setDescription(String description);
+
+    /**
+     * Return the cardinality of this property. The OSGi environment handles multi valued properties in arrays ([]) or in Vector objects. 
+     * The return value is defined as follows:<p>
+     *
+     * <ul>
+     * <li> x = Integer.MIN_VALUE    no limit, but use Vector</li>
+     * <li> x < 0                    -x = max occurrences, store in Vector</li>
+     * <li> x > 0                     x = max occurrences, store in array []</li>
+     * <li> x = Integer.MAX_VALUE    no limit, but use array []</li>
+     * <li> x = 0                     1 occurrence required</li>
+     * </ul>
+     */
+    public PropertyMetaData setCardinality(int cardinality);
+
+    /**
+     * Tells if this property is required or not.
+     */
+    public PropertyMetaData setRequired(boolean required);
+
+    /**
+     * Return a list of valid options for this property (the labels may be localized).
+     * @return the list of valid options for this property.
+     */
+    public PropertyMetaData addOption(String optionLabel, String optionValue);
+}
\ No newline at end of file

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,110 @@
+/*
+ * 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.felix.dm;
+
+import java.net.URL;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ResourceDependency extends Dependency, ComponentDependencyDeclaration, ResourceHandler {
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added or removed. When you specify callbacks, the auto configuration 
+     * feature is automatically turned off, because we're assuming you don't need it in this 
+     * case.
+     * 
+     * @param added the method to call when a service was added
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+	public ResourceDependency setCallbacks(String added, String removed) ;
+
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. When you specify callbacks, the auto 
+     * configuration feature is automatically turned off, because we're assuming you don't 
+     * need it in this case.
+     * 
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+     public ResourceDependency setCallbacks(String added, String changed, String removed);
+
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added or removed. They are called on the instance you provide. When you
+     * specify callbacks, the auto configuration feature is automatically turned off, because
+     * we're assuming you don't need it in this case.
+     * 
+     * @param instance the instance to call the callbacks on
+     * @param added the method to call when a service was added
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+     public ResourceDependency setCallbacks(Object instance, String added, String removed);
+    
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. They are called on the instance you provide. When you
+     * specify callbacks, the auto configuration feature is automatically turned off, because
+     * we're assuming you don't need it in this case.
+     * 
+     * @param instance the instance to call the callbacks on
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+     public ResourceDependency setCallbacks(Object instance, String added, String changed, String removed);
+        
+    /**
+     * Sets auto configuration for this service. Auto configuration allows the
+     * dependency to fill in any attributes in the service implementation that
+     * are of the same type as this dependency. Default is on.
+     * 
+     * @param autoConfig the value of auto config
+     * @return this service dependency
+     */
+     public ResourceDependency setAutoConfig(boolean autoConfig);
+    
+    /**
+     * Sets auto configuration for this service. Auto configuration allows the
+     * dependency to fill in the attribute in the service implementation that
+     * has the same type and instance name.
+     * 
+     * @param instanceName the name of attribute to auto config
+     * @return this service dependency
+     */
+     public ResourceDependency setAutoConfig(String instanceName);
+    
+     public ResourceDependency setResource(URL resource);
+	
+     public ResourceDependency setRequired(boolean required);
+
+     public ResourceDependency setFilter(String resourceFilter);
+     
+     public ResourceDependency setPropagate(boolean propagate);
+     
+     public ResourceDependency setPropagate(Object instance, String method);
+     
+     public ResourceDependency setInstanceBound(boolean isInstanceBound);
+}

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,75 @@
+/*
+ * 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.felix.dm;
+
+import java.net.URL;
+import java.util.Dictionary;
+
+/** 
+ * Service interface for anybody wanting to be notified of changes to resources. 
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ResourceHandler {
+    /** Name of the property that's used to describe the filter condition for a resource. */
+    public static final String FILTER = "filter";
+    /** Exact URL that this handler is looking for. Can be used instead of a filter to be very explicit about the resource you're looking for. */
+    public static final String URL = "url";
+    /** The host part of the URL. */
+    public static final String HOST = "host";
+    /** The path part of the URL. */
+    public static final String PATH = "path";
+    /** The protocol part of the URL. */
+    public static final String PROTOCOL = "protocol";
+    /** The port part of the URL. */
+    public static final String PORT = "port";
+
+    /**
+     * @deprecated Please use {@link #added(URL, Dictionary)} instead. When both are specified,
+     *     the new method takes precedence and the deprecated one is not invoked.
+     */
+	public void added(URL resource);
+	
+    /**
+     * Invoked whenever a new resource is added.
+     */
+	public void added(URL resource, Dictionary resourceProperties);
+	
+    /**
+     * @deprecated Please use {@link #changed(URL, Dictionary)} instead. When both are specified,
+     *     the new method takes precedence and the deprecated one is not invoked.
+     */
+	public void changed(URL resource);
+	
+    /**
+     * Invoked whenever an existing resource changes.
+     */
+	public void changed(URL resource, Dictionary resourceProperties);
+	
+    /**
+     * @deprecated Please use {@link #removed(URL, Dictionary)} instead. When both are specified,
+     *     the new method takes precedence and the deprecated one is not invoked.
+     */
+	public void removed(URL resource);
+	
+    /**
+     * Invoked whenever an existing resource is removed.
+     */
+	public void removed(URL resource, Dictionary resourceProperties);
+}

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,37 @@
+/*
+ * 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.felix.dm;
+
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ResourceUtil {
+    public static Dictionary createProperties(URL url) {
+        Properties props = new Properties();
+        props.setProperty(ResourceHandler.PROTOCOL, url.getProtocol());
+        props.setProperty(ResourceHandler.HOST, url.getHost());
+        props.setProperty(ResourceHandler.PORT, Integer.toString(url.getPort()));
+        props.setProperty(ResourceHandler.PATH, url.getPath());
+        return props;
+    }
+}

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,212 @@
+/*
+ * 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.felix.dm;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Service dependency that can track an OSGi service.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ServiceDependency extends Dependency, ComponentDependencyDeclaration {
+    /**
+     * Sets the name of the service that should be tracked. 
+     * 
+     * @param serviceName the name of the service
+     * @return this service dependency
+     */
+	public ServiceDependency setService(Class serviceName);
+    
+    /**
+     * Sets the name of the service that should be tracked. You can either specify
+     * only the name, or the name and a filter. In the latter case, the filter is used
+     * to track the service and should only return services of the type that was specified
+     * in the name. To make sure of this, the filter is actually extended internally to
+     * filter on the correct name.
+     * 
+     * @param serviceName the name of the service
+     * @param serviceFilter the filter condition
+     * @return this service dependency
+     */
+	public ServiceDependency setService(Class serviceName, String serviceFilter);
+    
+    /**
+     * Sets the filter for the services that should be tracked. Any service object
+     * matching the filter will be returned, without any additional filter on the
+     * class.
+     * 
+     * @param serviceFilter the filter condition
+     * @return this service dependency
+     */
+	public ServiceDependency setService(String serviceFilter);
+
+    /**
+     * Sets the name of the service that should be tracked. You can either specify
+     * only the name, or the name and a reference. In the latter case, the service reference
+     * is used to track the service and should only return services of the type that was 
+     * specified in the name.
+     * 
+     * @param serviceName the name of the service
+     * @param serviceReference the service reference to track
+     * @return this service dependency
+     */
+	public ServiceDependency setService(Class serviceName, ServiceReference serviceReference);
+    
+    /**
+     * Sets the default implementation for this service dependency. You can use this to supply
+     * your own implementation that will be used instead of a Null Object when the dependency is
+     * not available. This is also convenient if the service dependency is not an interface
+     * (which would cause the Null Object creation to fail) but a class.
+     * 
+     * @param implementation the instance to use or the class to instantiate if you want to lazily
+     *     instantiate this implementation
+     * @return this service dependency
+     */
+	public ServiceDependency setDefaultImplementation(Object implementation);
+
+    /**
+     * Sets the required flag which determines if this service is required or not.
+     * 
+     * @param required the required flag
+     * @return this service dependency
+     */
+	public ServiceDependency setRequired(boolean required);
+    
+    /**
+     * Sets auto configuration for this service. Auto configuration allows the
+     * dependency to fill in any attributes in the service implementation that
+     * are of the same type as this dependency. Default is on.
+     * 
+     * @param autoConfig the value of auto config
+     * @return this service dependency
+     */
+	public ServiceDependency setAutoConfig(boolean autoConfig);
+    
+    /**
+     * Sets auto configuration for this service. Auto configuration allows the
+     * dependency to fill in the attribute in the service implementation that
+     * has the same type and instance name.
+     * 
+     * @param instanceName the name of attribute to auto config
+     * @return this service dependency
+     */
+	public ServiceDependency setAutoConfig(String instanceName);
+    
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added or removed. When you specify callbacks, the auto configuration 
+     * feature is automatically turned off, because we're assuming you don't need it in this 
+     * case.
+     * 
+     * @param added the method to call when a service was added
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+	public ServiceDependency setCallbacks(String added, String removed);
+    
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. When you specify callbacks, the auto 
+     * configuration feature is automatically turned off, because we're assuming you don't 
+     * need it in this case.
+     * 
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+	public ServiceDependency setCallbacks(String added, String changed, String removed);
+
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. When you specify callbacks, the auto 
+     * configuration feature is automatically turned off, because we're assuming you don't 
+     * need it in this case.
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @param swapped the method to call when the service was swapped due to addition or 
+     * removal of an aspect
+     * @return this service dependency
+     */
+    public ServiceDependency setCallbacks(String added, String changed, String removed, String swapped);
+    
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added or removed. They are called on the instance you provide. When you
+     * specify callbacks, the auto configuration feature is automatically turned off, because
+     * we're assuming you don't need it in this case.
+     * 
+     * @param instance the instance to call the callbacks on
+     * @param added the method to call when a service was added
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+	public ServiceDependency setCallbacks(Object instance, String added, String removed);
+    
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. They are called on the instance you provide. When you
+     * specify callbacks, the auto configuration feature is automatically turned off, because
+     * we're assuming you don't need it in this case.
+     * 
+     * @param instance the instance to call the callbacks on
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+	public ServiceDependency setCallbacks(Object instance, String added, String changed, String removed);
+    
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. When you specify callbacks, the auto 
+     * configuration feature is automatically turned off, because we're assuming you don't 
+     * need it in this case.
+     * @param instance the instance to call the callbacks on
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @param swapped the method to call when the service was swapped due to addition or 
+     * removal of an aspect
+     * @return this service dependency
+     */    
+    public ServiceDependency setCallbacks(Object instance, String added, String changed, String removed, String swapped);
+	
+    /**
+     * Sets propagation of the service dependency properties to the provided service properties. Any additional
+     * service properties specified directly are merged with these.
+     */
+    public ServiceDependency setPropagate(boolean propagate);
+    
+    /**
+     * Sets an Object instance and a callback method used to propagate some properties to the provided service properties.
+     * The method will be invoked on the specified object instance and must have one of the following signatures:<p>
+     * <ul><li>Dictionary callback(ServiceReference, Object service) 
+     * <li>Dictionary callback(ServiceReference)
+     * </ul>
+     * @param instance the Object instance which is used to retrieve propagated service properties 
+     * @param method the method to invoke for retrieving the properties to be propagated to the service properties.
+     * @return this service dependency.
+     */
+    public ServiceDependency setPropagate(Object instance, String method);
+
+    public ServiceDependency setInstanceBound(boolean isInstanceBound);    
+}

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceUtil.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceUtil.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceUtil.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,175 @@
+/*
+ * 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.felix.dm;
+
+import java.util.List;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * OSGi service utilities.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceUtil {
+    /**
+     * Returns the service ranking of a service, based on its service reference. If
+     * the service has a property specifying its ranking, that will be returned. If
+     * not, the default ranking of zero will be returned.
+     * 
+     * @param ref the service reference to determine the ranking for
+     * @return the ranking
+     */
+    public static int getRanking(ServiceReference ref) {
+        return getRankingAsInteger(ref).intValue();
+    }
+    
+    /**
+     * Returns the service ranking of a service, based on its service reference. If
+     * the service has a property specifying its ranking, that will be returned. If
+     * not, the default ranking of zero will be returned.
+     * 
+     * @param ref the service reference to determine the ranking for
+     * @return the ranking
+     */
+    public static Integer getRankingAsInteger(ServiceReference ref) {
+        Integer rank = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+        if (rank != null) {
+            return rank;
+        }
+        return new Integer(0);
+    }
+    
+    /**
+     * Returns the service ID of a service, based on its service reference. This
+     * method is aware of service aspects as defined by the dependency manager and
+     * will return the ID of the orginal service if you give it an aspect.
+     * 
+     * @param ref the service reference to determine the service ID of
+     * @return the service ID
+     */
+    public static long getServiceId(ServiceReference ref) {
+        return getServiceIdAsLong(ref).longValue();
+    }
+    
+    /**
+     * Returns the service ID of a service, based on its service reference. This
+     * method is aware of service aspects as defined by the dependency manager and
+     * will return the ID of the orginal service if you give it an aspect.
+     * 
+     * @param ref the service reference to determine the service ID of
+     * @return the service ID
+     */
+    public static Long getServiceIdAsLong(ServiceReference ref) {
+    	return getServiceIdObject(ref);
+    }
+    
+    public static Long getServiceIdObject(ServiceReference ref) {
+        Long aid = (Long) ref.getProperty(DependencyManager.ASPECT);
+        if (aid != null) {
+            return aid;
+        }
+        Long sid = (Long) ref.getProperty(Constants.SERVICE_ID);
+        if (sid != null) {
+            return sid;
+        }
+        throw new IllegalArgumentException("Invalid service reference, no service ID found");
+    }
+
+    /**
+     * Determines if the service is an aspect as defined by the dependency manager.
+     * Aspects are defined by a property and this method will check for its presence.
+     * 
+     * @param ref the service reference
+     * @return <code>true</code> if it's an aspect, <code>false</code> otherwise
+     */
+    public static boolean isAspect(ServiceReference ref) {
+        Long aid = (Long) ref.getProperty(DependencyManager.ASPECT);
+        return (aid != null);
+    }
+    
+    /**
+     * Converts a service reference to a string, listing both the bundle it was
+     * registered from and all properties.
+     * 
+     * @param ref the service reference
+     * @return a string representation of the service
+     */
+    public static String toString(ServiceReference ref) {
+        if (ref == null) {
+            return "ServiceReference[null]";
+        }
+        else {
+            StringBuffer buf = new StringBuffer();
+            Bundle bundle = ref.getBundle();
+            if (bundle != null) {
+                buf.append("ServiceReference[");
+                buf.append(bundle.getBundleId());
+                buf.append("]{");
+            }
+            else {
+                buf.append("ServiceReference[unregistered]{");
+            }
+            buf.append(propertiesToString(ref, null));
+            buf.append("}");
+            return buf.toString();
+        }
+    }
+    
+    /**
+     * Converts the properties of a service reference to a string.
+     * 
+     * @param ref the service reference
+     * @param exclude a list of properties to exclude, or <code>null</code> to show everything
+     * @return a string representation of the service properties
+     */
+    public static String propertiesToString(ServiceReference ref, List /* <String> */ exclude) {
+        StringBuffer buf = new StringBuffer();
+        String[] keys = ref.getPropertyKeys();
+        for (int i = 0; i < keys.length; i++) {
+            if (i > 0) { 
+                buf.append(','); 
+            }
+            buf.append(keys[i]);
+            buf.append('=');
+            Object val = ref.getProperty(keys[i]);
+            if (exclude == null || !exclude.contains(val)) {
+                if (val instanceof String[]) {
+                    String[] valArray = (String[]) val;
+                    StringBuffer valBuf = new StringBuffer();
+                    valBuf.append('{');
+                    for (int j = 0; j < valArray.length; j++) {
+                        if (valBuf.length() > 1) {
+                            valBuf.append(',');
+                        }
+                        valBuf.append(valArray[j].toString());
+                    }
+                    valBuf.append('}');
+                    buf.append(valBuf);
+                }
+                else {
+                    buf.append(val.toString());
+                }
+            }
+        }
+        return buf.toString();
+    }
+}

Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/TemporalServiceDependency.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/TemporalServiceDependency.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/TemporalServiceDependency.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/TemporalServiceDependency.java Fri Feb 24 10:47:49 2012
@@ -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.felix.dm;
+
+/**
+ * A Temporal Service dependency that can block the caller thread between service updates. Only useful for required stateless
+ * dependencies that can be replaced transparently. A Dynamic Proxy is used to wrap the actual service dependency. When the
+ * dependency goes away, an attempt is made to replace it with another one which satisfies the service dependency criteria. If
+ * no service replacement is available, then any method invocation (through the dynamic proxy) will block during a configurable
+ * timeout. On timeout, an unchecked <code>IllegalStateException</code> exception is raised (but the service is not
+ * deactivated).
+ * <p>
+ * <b>This class only supports required dependencies, and temporal dependencies must be accessed outside the Activator (OSGi)
+ * thread, because method invocations may block the caller thread when dependencies are not satisfied. </b>
+ * <p>
+ * Sample Code:
+ * <p>
+ * <blockquote>
+ * 
+ * <pre>
+ * import org.apache.felix.dependencymanager.*;
+ * 
+ * public class Activator extends DependencyActivatorBase {
+ *   public void init(BundleContext ctx, DependencyManager dm) throws Exception {
+ *     dm.add(createService()
+ *            .setImplementation(MyServer.class)
+ *            .add(createTemporalServiceDependency()
+ *                .setTimeout(15000)
+ *                .setService(MyDependency.class)));
+ *   }
+ * 
+ *   public void destroy(BundleContext ctx, DependencyManager dm) throws Exception {
+ *   }
+ * }
+ * 
+ * class MyServer implements Runnable {
+ *   MyDependency _dependency; // Auto-Injected by reflection.
+ *   void start() {
+ *     (new Thread(this)).start();
+ *   }
+ *   
+ *   public void run() {
+ *     try {
+ *       _dependency.doWork();
+ *     } catch (IllegalStateException e) {
+ *       t.printStackTrace();
+ *     }
+ *   }
+ * </pre>
+ * 
+ * </blockquote>
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface TemporalServiceDependency extends ServiceDependency {
+    /**
+     * Sets the timeout for this temporal dependency. Specifying a timeout value of zero means that there is no timeout period,
+     * and an invocation on a missing service will fail immediately.
+     * 
+     * @param timeout the dependency timeout value greater or equals to 0
+     * @throws IllegalArgumentException if the timeout is negative
+     * @return this temporal dependency
+     */
+    TemporalServiceDependency setTimeout(long timeout);
+}