felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject svn commit: r884327 [1/2] - in /felix/trunk/dependencymanager: core/ core/src/main/java/org/apache/felix/dependencymanager/ core/src/main/java/org/apache/felix/dependencymanager/dependencies/ core/src/main/java/org/apache/felix/dependencymanager/impl/ ...
Date Wed, 25 Nov 2009 23:04:33 GMT
Author: marrs
Date: Wed Nov 25 23:04:32 2009
New Revision: 884327

URL: http://svn.apache.org/viewvc?rev=884327&view=rev
Log:
moved classes to subpackages, updated ServiceTracker to 4.2 spec, added BundleTracker and BundleDependency, ResourceDependency and some preliminary resource related classes (WIP)

Added:
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyService.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/BundleDependency.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ConfigurationDependency.java
      - copied, changed from r883744, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ResourceDependency.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ServiceDependency.java
      - copied, changed from r883744, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/TemporalServiceDependency.java
      - copied, changed from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/TemporalServiceDependency.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/DefaultNullObject.java
      - copied, changed from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DefaultNullObject.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/Logger.java
      - copied, changed from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Logger.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/SerialExecutor.java
      - copied, changed from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/SerialExecutor.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
      - copied, changed from r883744, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java
      - copied, changed from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java
      - copied, changed from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java
Removed:
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DefaultNullObject.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Logger.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/SerialExecutor.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/TemporalServiceDependency.java
Modified:
    felix/trunk/dependencymanager/core/pom.xml
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Dependency.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
    felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java

Modified: felix/trunk/dependencymanager/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/pom.xml?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/pom.xml (original)
+++ felix/trunk/dependencymanager/core/pom.xml Wed Nov 25 23:04:32 2009
@@ -53,7 +53,7 @@
             <Bundle-Description>A bundle that provides a run-time
               service dependency manager.</Bundle-Description>
             <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
-            <Export-Package>org.apache.felix.dependencymanager,org.apache.felix.dependencymanager.management,org.apache.felix.dependencymanager.tracker</Export-Package>
+            <Export-Package>org.apache.felix.dependencymanager,org.apache.felix.dependencymanager.management,org.apache.felix.dependencymanager.tracker,org.apache.felix.dependencymanager.impl,org.apache.felix.dependencymanager.dependencies,org.apache.felix.dependencymanager.resources</Export-Package>
             <Import-Package>!org.apache.felix.dependencymanager,*</Import-Package>
           </instructions>
         </configuration>

Modified: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Dependency.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Dependency.java?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Dependency.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Dependency.java Wed Nov 25 23:04:32 2009
@@ -49,6 +49,14 @@
     public boolean isAvailable();
     
     /**
+     * As soon as the instance is created, keep it around, even if this dependency
+     * goes away.
+     * 
+     * @return <code>true</code> if the dependency is instance bound
+     */
+    public boolean isInstanceBound();
+    
+    /**
      * Starts tracking the dependency. This activates some implementation
      * specific mechanism to do the actual tracking. If the tracking discovers
      * that the dependency becomes available, it should call 
@@ -56,7 +64,7 @@
      * 
      * @param service the service that is associated with this dependency
      */
-    public void start(Service service);
+    public void start(DependencyService service);
     
     /**
      * Stops tracking the dependency. This deactivates the tracking. If the
@@ -64,5 +72,5 @@
      * <code>dependencyUnavaible()</code> before stopping itself to ensure
      * that dependencies that aren't "active" are unavailable.
      */
-    public void stop(Service service);
+    public void stop(DependencyService service);
 }

Modified: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java Wed Nov 25 23:04:32 2009
@@ -20,6 +20,11 @@
 
 import java.util.List;
 
+import org.apache.felix.dependencymanager.dependencies.ConfigurationDependency;
+import org.apache.felix.dependencymanager.dependencies.ServiceDependency;
+import org.apache.felix.dependencymanager.dependencies.TemporalServiceDependency;
+import org.apache.felix.dependencymanager.impl.Logger;
+import org.apache.felix.dependencymanager.impl.ServiceImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
@@ -95,7 +100,7 @@
      * @return the new service
      */
     public Service createService() {
-        return new ServiceImpl(m_context, m_manager, m_logger);
+        return m_manager.createService();
     }
     
     /**
@@ -104,7 +109,7 @@
      * @return the service dependency
      */
     public ServiceDependency createServiceDependency() {
-        return new ServiceDependency(m_context, m_logger);
+        return m_manager.createServiceDependency();
     }
     
     /**
@@ -114,7 +119,7 @@
      * @return the service dependency
      */
     public TemporalServiceDependency createTemporalServiceDependency() {
-        return new TemporalServiceDependency(m_context, m_logger);
+        return m_manager.createTemporalServiceDependency();
     }
     
     /**

Modified: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java Wed Nov 25 23:04:32 2009
@@ -22,6 +22,11 @@
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.felix.dependencymanager.dependencies.ConfigurationDependency;
+import org.apache.felix.dependencymanager.dependencies.ServiceDependency;
+import org.apache.felix.dependencymanager.dependencies.TemporalServiceDependency;
+import org.apache.felix.dependencymanager.impl.Logger;
+import org.apache.felix.dependencymanager.impl.ServiceImpl;
 import org.osgi.framework.BundleContext;
 
 /**

Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyService.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyService.java?rev=884327&view=auto
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyService.java (added)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyService.java Wed Nov 25 23:04:32 2009
@@ -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.dependencymanager;
+
+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
+    public boolean isRegistered(); // impl method
+    public Object[] getCompositionInstances(); // impl method
+}

Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/BundleDependency.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/BundleDependency.java?rev=884327&view=auto
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/BundleDependency.java (added)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/BundleDependency.java Wed Nov 25 23:04:32 2009
@@ -0,0 +1,409 @@
+/*
+ * 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.dependencymanager.dependencies;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Dictionary;
+
+import org.apache.felix.dependencymanager.Dependency;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.Logger;
+import org.apache.felix.dependencymanager.impl.ServiceImpl;
+import org.apache.felix.dependencymanager.management.ServiceComponentDependency;
+import org.apache.felix.dependencymanager.tracker.BundleTracker;
+import org.apache.felix.dependencymanager.tracker.BundleTrackerCustomizer;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class BundleDependency implements Dependency, BundleTrackerCustomizer, ServiceComponentDependency {
+	private final BundleContext m_context;
+	private final Logger m_logger;
+	private boolean m_isStarted;
+	private BundleTracker m_tracker;
+	private int m_stateMask;
+	private boolean m_isAvailable;
+	private boolean m_isRequired;
+	private DependencyService m_service;
+	
+    private Object m_callbackInstance;
+    private String m_callbackAdded;
+    private String m_callbackChanged;
+    private String m_callbackRemoved;
+    private boolean m_autoConfig;
+	private Bundle m_bundleInstance;
+	private Filter m_filter;
+	private long m_bundleId = -1;
+
+
+	public BundleDependency(BundleContext context, Logger logger) {
+		m_context = context;
+		m_logger = logger;
+		m_autoConfig = true;
+	}
+
+	public boolean isAvailable() {
+		return m_isAvailable;
+	}
+
+	public boolean isRequired() {
+		return m_isRequired;
+	}
+	
+	public boolean isInstanceBound() {
+		return false; // TODO for now we are never bound to the service implementation instance
+	}
+
+	public void start(DependencyService service) {
+		synchronized (this) {
+			if (m_isStarted) {
+				throw new IllegalStateException("Dependency was already started." + getName());
+			}
+			m_service = service;
+			m_tracker = new BundleTracker(m_context, m_stateMask, this);
+			m_isStarted = true;
+		}
+		m_tracker.open();
+		System.out.println("START BD " + m_tracker);
+	}
+
+	public void stop(DependencyService service) {
+        synchronized (this) {
+            if (!m_isStarted) {
+                throw new IllegalStateException("Dependency was not started.");
+            }
+            m_isStarted = false;
+        }
+        m_tracker.close();
+        m_tracker = null;
+	}
+
+	public String getName() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public int getState() {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	public String getType() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Object addingBundle(Bundle bundle, BundleEvent event) {
+		System.out.println("ADDING " + bundle + " " + event);
+		// if we don't like a bundle, we could reject it here by returning null
+		if (m_bundleId >= 0 && m_bundleId != bundle.getBundleId()) {
+			return null;
+		}
+		Filter filter = m_filter;
+		if (filter != null) {
+			Dictionary headers = bundle.getHeaders();
+			if (!m_filter.match(headers)) {
+				return null;
+			}
+		}
+        return bundle;
+	}
+	
+	public void addedBundle(Bundle bundle, BundleEvent event, Object object) {
+		System.out.println("ADDED " + bundle + " " + event);
+        if (makeAvailable()) {
+            m_service.dependencyAvailable(this);
+        }
+        else {
+            m_service.dependencyChanged(this);
+        }
+        // try to invoke callback, if specified, but only for optional dependencies
+        // because callbacks for required dependencies are handled differently
+        if (!isRequired()) {
+            invokeAdded(bundle);
+        }
+	}
+
+	public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+		System.out.println("MODIFIED " + bundle + " " + event);
+        m_service.dependencyChanged(this);
+        // only invoke the changed callback if the service itself is "active"
+        if (((ServiceImpl) m_service).isRegistered()) {
+            invokeChanged(bundle);
+        }
+	}
+
+	public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+		System.out.println("REMOVED " + bundle + " " + event);
+        if (makeUnavailable()) {
+            m_service.dependencyUnavailable(this);
+        }
+        // try to invoke callback, if specified, but only for optional dependencies
+        // because callbacks for required dependencies are handled differently
+        if (!isRequired()) {
+            invokeRemoved(bundle);
+        }
+	}
+	
+    private synchronized boolean makeAvailable() {
+        if (!m_isAvailable) {
+            m_isAvailable = true;
+            return true;
+        }
+        return false;
+    }
+    
+    private synchronized boolean makeUnavailable() {
+        if ((m_isAvailable) && (m_tracker.getTrackingCount() == 0)) {
+            m_isAvailable = false;
+            return true;
+        }
+        return false;
+    }
+    
+    public void invokeAdded() {
+        invokeAdded(m_bundleInstance);
+    }
+    
+    public void invokeAdded(Bundle serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackAdded != null)) {
+                invokeCallbackMethod(callbackInstances, m_callbackAdded, serviceInstance);
+        }
+    }
+
+    public void invokeChanged(Bundle serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackChanged != null)) {
+//                if (m_reference == null) {
+//                    Thread.dumpStack();
+//                }
+                invokeCallbackMethod(callbackInstances, m_callbackChanged, serviceInstance);
+        }
+    }
+
+    
+    public void invokeRemoved() {
+        invokeRemoved(m_bundleInstance);
+    }
+    
+    public void invokeRemoved(Bundle serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackRemoved != null)) {
+//                if (m_reference == null) {
+//                    Thread.dumpStack();
+//                }
+                invokeCallbackMethod(callbackInstances, m_callbackRemoved, serviceInstance);
+        }
+    }
+    
+
+    
+    
+    private void invokeCallbackMethod(Object[] instances, String methodName, Object service) {
+        for (int i = 0; i < instances.length; i++) {
+            try {
+                invokeCallbackMethod(instances[i], methodName, service);
+            }
+            catch (NoSuchMethodException e) {
+                m_logger.log(Logger.LOG_DEBUG, "Method '" + methodName + "' does not exist on " + instances[i] + ". Callback skipped.");
+            }
+        }
+    }
+
+    private void invokeCallbackMethod(Object instance, String methodName, Object service) throws NoSuchMethodException {
+        Class currentClazz = instance.getClass();
+        boolean done = false;
+        while (!done && currentClazz != null) {
+            done = invokeMethod(instance, currentClazz, methodName,
+                new Class[][] {{Bundle.class}, {Object.class}, {}},
+                new Object[][] {{service}, {service}, {}},
+                false);
+            if (!done) {
+                currentClazz = currentClazz.getSuperclass();
+            }
+        }
+        if (!done && currentClazz == null) {
+            throw new NoSuchMethodException(methodName);
+        }
+    }
+    
+    private boolean invokeMethod(Object object, Class clazz, String name, Class[][] signatures, Object[][] parameters, boolean isSuper) {
+        Method m = null;
+        for (int i = 0; i < signatures.length; i++) {
+            Class[] signature = signatures[i];
+            try {
+                m = clazz.getDeclaredMethod(name, signature);
+                if (!(isSuper && Modifier.isPrivate(m.getModifiers()))) {
+                    m.setAccessible(true);
+                    try {
+                        m.invoke(object, parameters[i]);
+                    }
+                    catch (InvocationTargetException e) {
+                        m_logger.log(Logger.LOG_ERROR, "Exception while invoking method " + m + ".", e);
+                    }
+                    // we did find and invoke the method, so we return true
+                    return true;
+                }
+            }
+            catch (NoSuchMethodException e) {
+                // ignore this and keep looking
+            }
+            catch (Exception e) {
+                // could not even try to invoke the method
+                m_logger.log(Logger.LOG_ERROR, "Exception while trying to invoke method " + m + ".", e);
+            }
+        }
+        return false;
+    }
+    
+    private synchronized Object[] getCallbackInstances() {
+        Object[] callbackInstances = ((ServiceImpl) m_service).getCompositionInstances();
+        if (m_callbackInstance == null) {
+            return callbackInstances;
+        }
+        Object[] res = new Object[callbackInstances.length + 1];
+        res[0] = m_callbackInstance; //this could also be extended to an array...?
+        System.arraycopy(callbackInstances, 0, res, 1, callbackInstances.length);
+        return res;
+    }
+    /**
+     * 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 synchronized BundleDependency setCallbacks(String added, String removed) {
+        return setCallbacks(null, added, null, 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 synchronized BundleDependency setCallbacks(String added, String changed, String removed) {
+        return setCallbacks(null, added, changed, 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 synchronized BundleDependency setCallbacks(Object instance, String added, String removed) {
+        return setCallbacks(instance, added, null, 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 synchronized BundleDependency setCallbacks(Object instance, String added, String changed, String removed) {
+        ensureNotActive();
+        // if at least one valid callback is specified, we turn off auto configuration
+        if (added != null || removed != null || changed != null) {
+            setAutoConfig(false);
+        }
+        m_callbackInstance = instance;
+        m_callbackAdded = added;
+        m_callbackChanged = changed;
+        m_callbackRemoved = removed;
+        return this;
+    }
+
+    private void ensureNotActive() {
+        if (m_tracker != null) {
+            throw new IllegalStateException("Cannot modify state while active.");
+        }
+    }
+    public synchronized BundleDependency setAutoConfig(boolean autoConfig) {
+        ensureNotActive();
+        m_autoConfig = autoConfig;
+        return this;
+    }
+    
+    public synchronized BundleDependency setRequired(boolean required) {
+        ensureNotActive();
+        m_isRequired = required;
+        return this;
+    }
+
+	public BundleDependency setBundle(Bundle bundle) {
+		m_bundleId = bundle.getBundleId();
+		return this;
+	}
+
+	public BundleDependency setFilter(String filter) throws IllegalArgumentException {
+		if (filter != null) {
+			try {
+				m_filter = m_context.createFilter(filter);
+			} 
+			catch (InvalidSyntaxException e) {
+				throw new IllegalArgumentException(e.getMessage());
+			}
+		}
+		return this;
+	}
+	
+	public BundleDependency setStateMask(int mask) {
+		m_stateMask = mask;
+		return this;
+	}
+	
+    public synchronized boolean isAutoConfig() {
+        return m_autoConfig;
+    }
+
+    public Bundle getBundle() {
+    	Bundle[] bundles = m_tracker.getBundles();
+    	if (bundles != null && bundles.length > 0) {
+    		return bundles[0];
+    	}
+    	return null;
+    }
+}

Copied: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ConfigurationDependency.java (from r883744, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java)
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ConfigurationDependency.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ConfigurationDependency.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java&r1=883744&r2=884327&rev=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ConfigurationDependency.java Wed Nov 25 23:04:32 2009
@@ -16,12 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.dependencies;
+
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Dictionary;
 import java.util.Properties;
 
+import org.apache.felix.dependencymanager.Dependency;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.apache.felix.dependencymanager.management.ServiceComponentDependency;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -53,7 +57,7 @@
 	private BundleContext m_context;
 	private String m_pid;
 	private ServiceRegistration m_registration;
-	private volatile Service m_service;
+	private volatile DependencyService m_service;
 	private Dictionary m_settings;
 	private boolean m_propagate;
 	private final Logger m_logger;
@@ -77,6 +81,11 @@
 		return true;
 	}
 	
+	public boolean isInstanceBound() {
+	    // for now, configuration dependencies never are
+	    return false;
+	}
+	
 	/**
 	 * Returns <code>true</code> when configuration properties should be propagated
 	 * as service properties.
@@ -89,14 +98,14 @@
 		return m_settings;
 	}
 	
-	public void start(Service service) {
+	public void start(DependencyService service) {
 		m_service = service;
 		Properties props = new Properties();
 		props.put(Constants.SERVICE_PID, m_pid);
 		m_registration = m_context.registerService(ManagedService.class.getName(), this, props);
 	}
 
-	public void stop(Service service) {
+	public void stop(DependencyService service) {
 		m_registration.unregister();
 		m_service = null;
 	}
@@ -109,7 +118,7 @@
 	public void updated(Dictionary settings) throws ConfigurationException {
 		// if non-null settings come in, we have to instantiate the service and
 		// apply these settings
-		((ServiceImpl) m_service).initService();
+		m_service.initService(); /// <<< CHANGES THE STATE, WHEN IT SHOULD NOT (YET) DO THAT (we should not use m_serviceInstance to determine the state but use a flag var instead)
 		Object service = m_service.getService();
 				
 		Dictionary oldSettings = null; 

Added: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ResourceDependency.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ResourceDependency.java?rev=884327&view=auto
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ResourceDependency.java (added)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ResourceDependency.java Wed Nov 25 23:04:32 2009
@@ -0,0 +1,362 @@
+/*
+ * 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.dependencymanager.dependencies;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Properties;
+
+import org.apache.felix.dependencymanager.Dependency;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.Logger;
+import org.apache.felix.dependencymanager.impl.ServiceImpl;
+import org.apache.felix.dependencymanager.resources.Resource;
+import org.apache.felix.dependencymanager.resources.ResourceHandler;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class ResourceDependency implements Dependency, ResourceHandler {
+	private volatile BundleContext m_context;
+	private volatile ServiceRegistration m_registration;
+	private long m_resourceCounter;
+
+    private Object m_callbackInstance;
+    private String m_callbackAdded;
+    private String m_callbackChanged;
+    private String m_callbackRemoved;
+    private boolean m_autoConfig;
+    private final Logger m_logger;
+    private String m_autoConfigInstance;
+    private DependencyService m_service;
+	private boolean m_isRequired;
+	private String m_resourceFilter;
+	private Resource m_resource;
+	private Resource m_trackedResource;
+
+	
+    public ResourceDependency(BundleContext context, Logger logger) {
+    	m_context = context;
+    	m_logger = logger;
+    	m_autoConfig = true;
+    }
+    
+	public synchronized boolean isAvailable() {
+		return m_resourceCounter > 0;
+	}
+
+	public boolean isRequired() {
+		return m_isRequired;
+	}
+	
+	public boolean isInstanceBound() {
+		return false; // TODO for now we are never bound to the service implementation instance
+	}
+
+	public void start(DependencyService service) {
+		m_service = service;
+		Properties props = new Properties();
+		// TODO create constant for this key
+		props.setProperty("filter", m_resourceFilter);
+		m_registration = m_context.registerService(ResourceHandler.class.getName(), this, props);
+		
+	}
+
+	public void stop(DependencyService service) {
+		m_registration.unregister();
+		m_registration = null;
+	}
+
+	public void added(Resource resource) {
+		System.out.println("RD ADDED " + resource);
+		long counter;
+		synchronized (this) {
+			m_resourceCounter++;
+			counter = m_resourceCounter;
+			m_resource = resource; // TODO this really sucks as a way to track a single resource
+		}
+        if (counter == 1) {
+            m_service.dependencyAvailable(this);
+        }
+        else {
+            m_service.dependencyChanged(this);
+        }
+        // try to invoke callback, if specified, but only for optional dependencies
+        // because callbacks for required dependencies are handled differently
+        if (!isRequired()) {
+            invokeAdded(resource);
+        }
+	}
+
+	public void changed(Resource resource) {
+		invokeChanged(resource);
+	}
+
+	public void removed(Resource resource) {
+		long counter;
+		synchronized (this) {
+			m_resourceCounter--;
+			counter = m_resourceCounter;
+		}
+        if (counter == 0) {
+            m_service.dependencyUnavailable(this);
+        }
+        // try to invoke callback, if specified, but only for optional dependencies
+        // because callbacks for required dependencies are handled differently
+        if (!isRequired()) {
+            invokeRemoved(resource);
+        }
+	}
+	
+    public void invokeAdded() {
+    	// TODO fixme
+        //invokeAdded(m_bundleInstance);
+    }
+
+    public void invokeAdded(Resource serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackAdded != null)) {
+                invokeCallbackMethod(callbackInstances, m_callbackAdded, serviceInstance);
+        }
+    }
+
+    public void invokeChanged(Resource serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackChanged != null)) {
+//                if (m_reference == null) {
+//                    Thread.dumpStack();
+//                }
+                invokeCallbackMethod(callbackInstances, m_callbackChanged, serviceInstance);
+        }
+    }
+
+    
+    public void invokeRemoved() {
+    	// TODO fixme
+        //invokeRemoved(m_bundleInstance);
+    }
+    
+    public void invokeRemoved(Resource serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackRemoved != null)) {
+//                if (m_reference == null) {
+//                    Thread.dumpStack();
+//                }
+                invokeCallbackMethod(callbackInstances, m_callbackRemoved, serviceInstance);
+        }
+    }
+
+
+
+	
+    /**
+     * 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 synchronized ResourceDependency setCallbacks(String added, String removed) {
+        return setCallbacks(null, added, null, 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 synchronized ResourceDependency setCallbacks(String added, String changed, String removed) {
+        return setCallbacks(null, added, changed, 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 synchronized ResourceDependency setCallbacks(Object instance, String added, String removed) {
+        return setCallbacks(instance, added, null, 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 synchronized ResourceDependency setCallbacks(Object instance, String added, String changed, String removed) {
+        ensureNotActive();
+        // if at least one valid callback is specified, we turn off auto configuration
+        if (added != null || removed != null || changed != null) {
+            setAutoConfig(false);
+        }
+        m_callbackInstance = instance;
+        m_callbackAdded = added;
+        m_callbackChanged = changed;
+        m_callbackRemoved = removed;
+        return this;
+    }
+    
+    private void ensureNotActive() {
+        if (m_registration != null) {
+            throw new IllegalStateException("Cannot modify state while active.");
+        }
+    }
+    
+    /**
+     * 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 synchronized ResourceDependency setAutoConfig(boolean autoConfig) {
+        ensureNotActive();
+        m_autoConfig = autoConfig;
+        return this;
+    }
+    
+    /**
+     * 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 synchronized ResourceDependency setAutoConfig(String instanceName) {
+        ensureNotActive();
+        m_autoConfig = (instanceName != null);
+        m_autoConfigInstance = instanceName;
+        return this;
+    }
+    
+    private void invokeCallbackMethod(Object[] instances, String methodName, Object service) {
+        for (int i = 0; i < instances.length; i++) {
+            try {
+                invokeCallbackMethod(instances[i], methodName, service);
+            }
+            catch (NoSuchMethodException e) {
+                m_logger.log(Logger.LOG_DEBUG, "Method '" + methodName + "' does not exist on " + instances[i] + ". Callback skipped.");
+            }
+        }
+    }
+
+    private void invokeCallbackMethod(Object instance, String methodName, Object service) throws NoSuchMethodException {
+        Class currentClazz = instance.getClass();
+        boolean done = false;
+        while (!done && currentClazz != null) {
+            done = invokeMethod(instance, currentClazz, methodName,
+                new Class[][] {{Resource.class}, {Object.class}, {}},
+                new Object[][] {{service}, {service}, {}},
+                false);
+            if (!done) {
+                currentClazz = currentClazz.getSuperclass();
+            }
+        }
+        if (!done && currentClazz == null) {
+            throw new NoSuchMethodException(methodName);
+        }
+    }
+    
+    private boolean invokeMethod(Object object, Class clazz, String name, Class[][] signatures, Object[][] parameters, boolean isSuper) {
+        Method m = null;
+        for (int i = 0; i < signatures.length; i++) {
+            Class[] signature = signatures[i];
+            try {
+                m = clazz.getDeclaredMethod(name, signature);
+                if (!(isSuper && Modifier.isPrivate(m.getModifiers()))) {
+                    m.setAccessible(true);
+                    try {
+                        m.invoke(object, parameters[i]);
+                    }
+                    catch (InvocationTargetException e) {
+                        m_logger.log(Logger.LOG_ERROR, "Exception while invoking method " + m + ".", e);
+                    }
+                    // we did find and invoke the method, so we return true
+                    return true;
+                }
+            }
+            catch (NoSuchMethodException e) {
+                // ignore this and keep looking
+            }
+            catch (Exception e) {
+                // could not even try to invoke the method
+                m_logger.log(Logger.LOG_ERROR, "Exception while trying to invoke method " + m + ".", e);
+            }
+        }
+        return false;
+    }
+    private synchronized Object[] getCallbackInstances() {
+        Object[] callbackInstances = ((ServiceImpl) m_service).getCompositionInstances();
+        if (m_callbackInstance == null) {
+            return callbackInstances;
+        }
+        Object[] res = new Object[callbackInstances.length + 1];
+        res[0] = m_callbackInstance; //this could also be extended to an array...?
+        System.arraycopy(callbackInstances, 0, res, 1, callbackInstances.length);
+        return res;
+    }
+
+	public ResourceDependency setResource(Resource resource) {
+		m_trackedResource = resource;
+		return this;
+	}
+	
+    public synchronized ResourceDependency setRequired(boolean required) {
+        ensureNotActive();
+        m_isRequired = required;
+        return this;
+    }
+
+	public ResourceDependency setFilter(String resourceFilter) {
+		m_resourceFilter = resourceFilter;
+		return this;
+	}
+    public synchronized boolean isAutoConfig() {
+        return m_autoConfig;
+    }
+
+    public Resource getResource() {
+    	System.out.println("Fetching resource");
+    	return m_resource;
+    }
+}

Copied: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ServiceDependency.java (from r883744, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java)
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ServiceDependency.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ServiceDependency.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java&r1=883744&r2=884327&rev=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ServiceDependency.java Wed Nov 25 23:04:32 2009
@@ -16,19 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.dependencies;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
 import java.util.AbstractMap;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.felix.dependencymanager.Dependency;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.DefaultNullObject;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.apache.felix.dependencymanager.management.ServiceComponentDependency;
 import org.apache.felix.dependencymanager.tracker.ServiceTracker;
 import org.apache.felix.dependencymanager.tracker.ServiceTrackerCustomizer;
@@ -44,7 +50,7 @@
  */
 public class ServiceDependency implements Dependency, ServiceTrackerCustomizer, ServiceComponentDependency {
     private boolean m_isRequired;
-    protected Service m_service;
+    protected List m_services = new ArrayList();
     protected volatile ServiceTracker m_tracker;
     protected BundleContext m_context;
     private boolean m_isAvailable;
@@ -66,6 +72,7 @@
     private boolean m_autoConfigInvoked;
     private Object m_defaultImplementation;
     private Object m_defaultImplementationInstance;
+    private boolean m_isInstanceBound;
     
     private static final Comparator COMPARATOR = new Comparator() {
         public int getRank(ServiceReference ref) {
@@ -188,6 +195,10 @@
     public synchronized boolean isAutoConfig() {
         return m_autoConfig;
     }
+    
+    public boolean isInstanceBound() {
+        return m_isInstanceBound;
+    }
 
     public synchronized Object getService() {
         Object service = null;
@@ -246,6 +257,45 @@
         }
         return service;
     }
+    
+    // TODO lots of duplication in lookupService()
+    public ServiceReference lookupServiceReference() {
+        ServiceReference service = null;
+        if (m_isStarted) {
+            service = m_tracker.getServiceReference();
+        }
+        else {
+            ServiceReference[] refs = null;
+            ServiceReference ref = null;
+            if (m_trackedServiceName != null) {
+                if (m_trackedServiceFilter != null) {
+                    try {
+                        refs = m_context.getServiceReferences(m_trackedServiceName.getName(), m_trackedServiceFilter);
+                        if (refs != null) {
+                            Arrays.sort(refs, COMPARATOR);
+                            ref = refs[0];
+                        }
+                    }
+                    catch (InvalidSyntaxException e) {
+                        throw new IllegalStateException("Invalid filter definition for dependency.");
+                    }
+                }
+                else if (m_trackedServiceReference != null) {
+                    ref = m_trackedServiceReference;
+                }
+                else {
+                    ref = m_context.getServiceReference(m_trackedServiceName.getName());
+                }
+                if (ref != null) {
+                    service = ref;
+                }
+            }
+            else {
+                throw new IllegalStateException("Could not lookup dependency, no service name specified.");
+            }
+        }
+        return service;
+    }
 
     private Object getNullObject() {
         if (m_nullObject == null) {
@@ -284,45 +334,52 @@
         return m_trackedServiceName;
     }
 
-    public void start(Service service) {
+    public void start(DependencyService service) {
+        boolean needsStarting = false;
         synchronized (this) {
-            if (m_isStarted) {
-                throw new IllegalStateException("Service dependency was already started." + m_trackedServiceName);
-            }
-            m_service = service;
-            if (m_trackedServiceName != null) {
-                if (m_trackedServiceFilter != null) {
-                    try {
-                        m_tracker = new ServiceTracker(m_context, m_context.createFilter(m_trackedServiceFilter), this);
+            m_services.add(service);
+            if (!m_isStarted) {
+                if (m_trackedServiceName != null) {
+                    if (m_trackedServiceFilter != null) {
+                        try {
+                            m_tracker = new ServiceTracker(m_context, m_context.createFilter(m_trackedServiceFilter), this);
+                        }
+                        catch (InvalidSyntaxException e) {
+                            throw new IllegalStateException("Invalid filter definition for dependency.");
+                        }
                     }
-                    catch (InvalidSyntaxException e) {
-                        throw new IllegalStateException("Invalid filter definition for dependency.");
+                    else if (m_trackedServiceReference != null) {
+                        m_tracker = new ServiceTracker(m_context, m_trackedServiceReference, this);
+                    }
+                    else {
+                        m_tracker = new ServiceTracker(m_context, m_trackedServiceName.getName(), this);
                     }
-                }
-                else if (m_trackedServiceReference != null) {
-                    m_tracker = new ServiceTracker(m_context, m_trackedServiceReference, this);
                 }
                 else {
-                    m_tracker = new ServiceTracker(m_context, m_trackedServiceName.getName(), this);
+                    throw new IllegalStateException("Could not create tracker for dependency, no service name specified.");
                 }
+                m_isStarted = true;
+                needsStarting = true;
             }
-            else {
-                throw new IllegalStateException("Could not create tracker for dependency, no service name specified.");
-            }
-            m_isStarted = true;
         }
-        m_tracker.open();
+        if (needsStarting) {
+            m_tracker.open();
+        }
     }
 
-    public void stop(Service service) {
+    public void stop(DependencyService service) {
+        boolean needsStopping = false;
         synchronized (this) {
-            if (!m_isStarted) {
-                throw new IllegalStateException("Service dependency was not started.");
+            m_services.remove(service);
+            if (m_services.size() == 0) {
+                m_isStarted = false;
+                needsStopping = true;
             }
-            m_isStarted = false;
         }
-        m_tracker.close();
-        m_tracker = null;
+        if (needsStopping) {
+            m_tracker.close();
+            m_tracker = null;
+        }
     }
 
     public Object addingService(ServiceReference ref) {
@@ -339,26 +396,26 @@
     }
 
     public void addedService(ServiceReference ref, Object service) {
-        if (makeAvailable()) {
-            m_service.dependencyAvailable(this);
-            // try to invoke callback, if specified, but only for optional dependencies
-            // because callbacks for required dependencies are handled differently
-            if (!isRequired()) {
-                invokeAdded(ref, service);
+        boolean makeAvailable = makeAvailable();
+        
+        Object[] services = m_services.toArray();
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            if (makeAvailable) {
+                ds.dependencyAvailable(this);
+                if (!isRequired()) {
+                    invokeAdded(ds, ref, service);
+                }
+            }
+            else {
+                ds.dependencyChanged(this);
+                invokeAdded(ds, ref, service);
             }
-        }
-        else {
-            m_service.dependencyChanged(this);
-            invokeAdded(ref, service);
         }
     }
 
-    public void invokeAdded() {
-        invokeAdded(m_reference, m_serviceInstance);
-    }
-    
-    public void invokeAdded(ServiceReference reference, Object serviceInstance) {
-        Object[] callbackInstances = getCallbackInstances();
+    public void invokeAdded(DependencyService dependencyService, ServiceReference reference, Object serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances(dependencyService);
         if ((callbackInstances != null) && (m_callbackAdded != null)) {
             invokeCallbackMethod(callbackInstances, m_callbackAdded, reference, serviceInstance);
         }
@@ -367,49 +424,53 @@
     public void modifiedService(ServiceReference ref, Object service) {
         m_reference = ref;
         m_serviceInstance = service;
-        m_service.dependencyChanged(this);
-        // only invoke the changed callback if the service itself is "active"
-        if (((ServiceImpl) m_service).isRegistered()) {
-            invokeChanged(ref, service);
+        
+        Object[] services = m_services.toArray();
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            ds.dependencyChanged(this);
+            if (ds.isRegistered()) {
+                invokeChanged(ds, ref, service);
+            }
         }
     }
 
-    public void invokeChanged(ServiceReference reference, Object serviceInstance) {
-        Object[] callbackInstances = getCallbackInstances();
+    public void invokeChanged(DependencyService dependencyService, ServiceReference reference, Object serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances(dependencyService);
         if ((callbackInstances != null) && (m_callbackChanged != null)) {
             invokeCallbackMethod(callbackInstances, m_callbackChanged, reference, serviceInstance);
         }
     }
 
     public void removedService(ServiceReference ref, Object service) {
-        if (makeUnavailable()) {
-            m_service.dependencyUnavailable(this);
-            // try to invoke callback, if specified, but only for optional dependencies
-            // because callbacks for required dependencies are handled differently
-            if (!isRequired()) {
-                invokeRemoved(ref, service);
+        boolean makeUnavailable = makeUnavailable();
+        
+        Object[] services = m_services.toArray();
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            if (makeUnavailable) {
+                ds.dependencyUnavailable(this);
+                if (!isRequired()) {
+                    invokeRemoved(ds, ref, service);
+                }
+            }
+            else {
+                ds.dependencyChanged(this);
+                invokeRemoved(ds, ref, service);
             }
         }
-        else {
-            m_service.dependencyChanged(this);
-            invokeRemoved(ref, service);
-        }
-        
         // unget what we got in addingService (see ServiceTracker 701.4.1)
         m_context.ungetService(ref);
-    }
 
-    public void invokeRemoved() {
-        invokeRemoved(m_reference, m_serviceInstance);
     }
-    
-    public void invokeRemoved(ServiceReference reference, Object serviceInstance) {
-        Object[] callbackInstances = getCallbackInstances();
+
+    public void invokeRemoved(DependencyService dependencyService, ServiceReference reference, Object serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances(dependencyService);
         if ((callbackInstances != null) && (m_callbackRemoved != null)) {
             invokeCallbackMethod(callbackInstances, m_callbackRemoved, reference, serviceInstance);
         }
     }
-    
+
     protected synchronized boolean makeAvailable() {
         if (!m_isAvailable) {
             m_isAvailable = true;
@@ -426,8 +487,13 @@
         return false;
     }
     
-    private synchronized Object[] getCallbackInstances() {
-        return m_callbackInstance != null ? new Object[] { m_callbackInstance } : ((ServiceImpl) m_service).getCompositionInstances();
+    private synchronized Object[] getCallbackInstances(DependencyService dependencyService) {
+        if (m_callbackInstance == null) {
+            return dependencyService.getCompositionInstances();
+        }
+        else {
+            return new Object[] { m_callbackInstance };
+        }
     }
 
     private void invokeCallbackMethod(Object[] instances, String methodName, ServiceReference reference, Object service) {
@@ -588,6 +654,11 @@
         m_isRequired = required;
         return this;
     }
+    
+    public ServiceDependency setInstanceBound(boolean isInstanceBound) {
+        m_isInstanceBound = isInstanceBound;
+        return this;
+    }
 
     /**
      * Sets auto configuration for this service. Auto configuration allows the

Copied: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/TemporalServiceDependency.java (from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/TemporalServiceDependency.java)
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/TemporalServiceDependency.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/TemporalServiceDependency.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/TemporalServiceDependency.java&r1=883483&r2=884327&rev=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/TemporalServiceDependency.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/TemporalServiceDependency.java Wed Nov 25 23:04:32 2009
@@ -9,12 +9,15 @@
  * or implied. See the License for the specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.dependencies;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 
+import org.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 
@@ -110,12 +113,18 @@
      * The ServiceTracker calls us here in order to inform about a service arrival.
      */
     public synchronized void addedService(ServiceReference ref, Object service) {
-        if (makeAvailable()) {
-            // So far, our dependency was not satisfied: wrap the service behind our proxy.
+        boolean makeAvailable = makeAvailable();
+        if (makeAvailable) {
             m_serviceInstance = Proxy.newProxyInstance(m_trackedServiceName.getClassLoader(), new Class[] { m_trackedServiceName }, this);
-            m_service.dependencyAvailable(this); // will invoke "added" callbacks, if any.
         }
-        else {
+        Object[] services = m_services.toArray();
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            if (makeAvailable) {
+                ds.dependencyAvailable(this);
+            }
+        }
+        if (!makeAvailable) {
             notifyAll();
         }
     }

Copied: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/DefaultNullObject.java (from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DefaultNullObject.java)
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/DefaultNullObject.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/DefaultNullObject.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DefaultNullObject.java&r1=883483&r2=884327&rev=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DefaultNullObject.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/DefaultNullObject.java Wed Nov 25 23:04:32 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.impl;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;

Copied: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/Logger.java (from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Logger.java)
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/Logger.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/Logger.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Logger.java&r1=883483&r2=884327&rev=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Logger.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/Logger.java Wed Nov 25 23:04:32 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.impl;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;

Copied: felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/SerialExecutor.java (from r883483, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/SerialExecutor.java)
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/SerialExecutor.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/SerialExecutor.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/SerialExecutor.java&r1=883483&r2=884327&rev=884327&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/SerialExecutor.java (original)
+++ felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/SerialExecutor.java Wed Nov 25 23:04:32 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.impl;
 
 import java.util.LinkedList;
 import java.util.NoSuchElementException;



Mime
View raw message