FELIX-3292 Applied the second patch. Removed one callback signature that should have been removed, added @deprecated tags and some comments.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1226436 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
index b1649b2..8d3a04d 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
@@ -18,8 +18,6 @@
  */
 package org.apache.felix.dm;
 
-import java.util.List;
-
 import org.apache.felix.dm.impl.Logger;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
@@ -243,7 +241,7 @@
     public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove) {
         return m_manager.createAdapterService(serviceInterface, serviceFilter, add, change, remove);
     }
-
+    
     /**
      * Creates a new resource adapter service.
      * 
@@ -258,8 +256,26 @@
      * 
      * @return the resource adapter service
      */
+    public Component createResourceAdapter(String resourceFilter, boolean propagate, Object callbackInstance, String callbackSet, String callbackChanged) {
+        return m_manager.createResourceAdapterService(resourceFilter, propagate, callbackInstance, callbackSet, callbackChanged);
+    }
+    
+    /**
+     * Creates a new resource adapter service.
+     * 
+     * @return the resource adapter service
+     */
     public Component createResourceAdapter(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
-        return m_manager.createResourceAdapterService(resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, callbackChanged);
+        return m_manager.createResourceAdapterService(resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, null, callbackChanged);
+    }
+    
+    /**
+     * Creates a new resource adapter service.
+     * 
+     * @return the resource adapter service
+     */
+    public Component createResourceAdapter(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged) {
+        return m_manager.createResourceAdapterService(resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, callbackSet, callbackChanged);
     }
     
     /**
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
index c6032eb..3da661d 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
@@ -417,6 +417,7 @@
      * </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 
@@ -424,11 +425,19 @@
      * @see Resource
      */
     public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackChanged) {
-        return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, 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, 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);
     }
     
     /**
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java
index cedb4e1..2414027 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java
@@ -19,6 +19,7 @@
 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. 
@@ -30,7 +31,6 @@
     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. */
@@ -40,10 +40,36 @@
     /** The port part of the URL. */
     public static final String PORT = "port";
 
-    /** Invoked whenever a new resource is added. */
+    /**
+     * @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 an existing resource changes. */
+	
+    /**
+     * 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 is removed. */
+	
+    /**
+     * 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);
 }
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java
index f8823f2..093acdb 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java
@@ -38,49 +38,50 @@
 public class ResourceAdapterServiceImpl extends FilterService {
     private Object m_callbackInstance = null;
     private String m_callbackChanged = "changed";
+    private String m_callbackAdded = "setResource";
     
     /**
      * Creates a new Resource Adapter Service implementation.
      * @param dm the dependency manager used to create our internal adapter service
      */
-    public ResourceAdapterServiceImpl(DependencyManager dm, String resourceFilter, boolean propagate, Object callbackInstance, String callbackChanged) {
+    public ResourceAdapterServiceImpl(DependencyManager dm, String resourceFilter, boolean propagate, Object callbackInstance, String callbackSet, String callbackChanged) {
         super(dm.createComponent()); // This service will be filtered by our super class, allowing us to take control.
         m_callbackInstance = callbackInstance;
+        m_callbackAdded = callbackSet;
         m_callbackChanged = callbackChanged;
-        m_component.setImplementation(new ResourceAdapterImpl(resourceFilter, propagate))
+        m_component.setImplementation(new ResourceAdapterImpl(propagate))
             .add(dm.createResourceDependency()
                  .setFilter(resourceFilter)
                  .setAutoConfig(false)
                  .setCallbacks("added", "removed"));
     }
-
-    public ResourceAdapterServiceImpl(DependencyManager dm, String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
+    
+    public ResourceAdapterServiceImpl(DependencyManager dm, String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged) {
         super(dm.createComponent()); // This service will be filtered by our super class, allowing us to take control.
         m_callbackInstance = callbackInstance;
+        m_callbackAdded = callbackSet;
         m_callbackChanged = callbackChanged;
-        m_component.setImplementation(new ResourceAdapterImpl(resourceFilter, propagateCallbackInstance, propagateCallbackMethod))
+        m_component.setImplementation(new ResourceAdapterImpl(propagateCallbackInstance, propagateCallbackMethod))
             .add(dm.createResourceDependency()
                  .setFilter(resourceFilter)
                  .setAutoConfig(false)
                  .setCallbacks("added", "removed"));
-    }
+    }   
 
     public class ResourceAdapterImpl extends AbstractDecorator {
-        private final String m_resourceFilter;
         private final boolean m_propagate;
         private final Object m_propagateCallbackInstance;
         private final String m_propagateCallbackMethod;
 
-        public ResourceAdapterImpl(String resourceFilter, boolean propagate) {
-            this(resourceFilter, propagate, null, null);
+        public ResourceAdapterImpl(boolean propagate) {
+            this(propagate, null, null);
         }
 
-        public ResourceAdapterImpl(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod) {
-            this(resourceFilter, true, propagateCallbackInstance, propagateCallbackMethod);
+        public ResourceAdapterImpl(Object propagateCallbackInstance, String propagateCallbackMethod) {
+            this(true, propagateCallbackInstance, propagateCallbackMethod);
         }
         
-        private ResourceAdapterImpl(String resourceFilter, boolean propagate, Object propagateCallbackInstance, String propagateCallbackMethod) {
-            m_resourceFilter = resourceFilter;
+        private ResourceAdapterImpl(boolean propagate, Object propagateCallbackInstance, String propagateCallbackMethod) {
             m_propagate = propagate;
             m_propagateCallbackInstance = propagateCallbackInstance;
             m_propagateCallbackMethod = propagateCallbackMethod;
@@ -102,8 +103,8 @@
             dependencies.remove(0);
             ResourceDependency resourceDependency = m_manager.createResourceDependency()
                  .setResource(resource)
-                 .setCallbacks(m_callbackInstance, null, m_callbackChanged, null)
-                 .setAutoConfig(true)
+                 .setCallbacks(m_callbackInstance, m_callbackAdded, m_callbackChanged, null)
+                 .setAutoConfig(m_callbackAdded == null)
                  .setRequired(true);
             if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
                 resourceDependency.setPropagate(m_propagateCallbackInstance, m_propagateCallbackMethod);
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
index 7111d36..9b11fbb 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
@@ -22,6 +22,7 @@
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Dictionary;
+import java.util.Enumeration;
 import java.util.List;
 import java.util.Properties;
 
@@ -54,7 +55,9 @@
 	private String m_resourceFilter;
 	private URL m_trackedResource;
     private List m_resources = new ArrayList();
+    private List m_resourceProperties = new ArrayList();
     private URL m_resourceInstance;
+    private Dictionary m_resourcePropertiesInstance;
     private boolean m_propagate;
     private Object m_propagateCallbackInstance;
     private String m_propagateCallbackMethod;
@@ -102,9 +105,11 @@
                 props = new Properties();
                 props.put(ResourceHandler.URL, m_trackedResource);
 	        }
-	        else if (m_resourceFilter != null) {
-	            props = new Properties();
-	            props.put(ResourceHandler.FILTER, m_resourceFilter);
+	        else { 
+	        	if (m_resourceFilter != null) {
+		            props = new Properties();
+		            props.put(ResourceHandler.FILTER, m_resourceFilter);
+	        	}
 	        }
 	        m_registration = m_context.registerService(ResourceHandler.class.getName(), this, props);
 	    }
@@ -126,11 +131,20 @@
 	}
 
 	public void added(URL resource) {
+		handleResourceAdded(resource, null);
+	}
+	
+	public void added(URL resource, Dictionary resourceProperties) {
+		handleResourceAdded(resource, resourceProperties);
+	}
+	
+	private void handleResourceAdded(URL resource, Dictionary resourceProperties) {
 	    if (m_trackedResource == null || m_trackedResource.equals(resource)) {
     		long counter;
     		Object[] services;
     		synchronized (this) {
     		    m_resources.add(resource);
+    		    m_resourceProperties.add(resourceProperties);
     			counter = m_resources.size();
     			services = m_services.toArray();
     		}
@@ -139,35 +153,54 @@
                 if (counter == 1) {
                     ds.dependencyAvailable(this);
                     if (!isRequired()) {
-                        invokeAdded(ds, resource);
+                        invokeAdded(ds, resource, resourceProperties);
                     }
                 }
                 else {
                     ds.dependencyChanged(this);
-                    invokeAdded(ds, resource);
+                    invokeAdded(ds, resource, resourceProperties);
                 }
             }
 	    }
 	}
-
+	
 	public void changed(URL resource) {
+		handleResourceChanged(resource, null);
+	}
+	
+	public void changed(URL resource, Dictionary resourceProperties) {
+		handleResourceChanged(resource, resourceProperties);
+	}
+
+	private void handleResourceChanged(URL resource, Dictionary resourceProperties) {
         if (m_trackedResource == null || m_trackedResource.equals(resource)) {
             Object[] services;
             synchronized (this) {
+            	// change the resource properties for the resource
+            	m_resourceProperties.set(m_resources.indexOf(resource), resourceProperties);
                 services = m_services.toArray();
             }
             for (int i = 0; i < services.length; i++) {
                 DependencyService ds = (DependencyService) services[i];
-                invokeChanged(ds, resource);
+                invokeChanged(ds, resource, resourceProperties);
             }
         }
 	}
-
+	
 	public void removed(URL resource) {
+		handleResourceRemoved(resource, null);
+	}
+	
+	public void removed(URL resource, Dictionary resourceProperties) {
+		handleResourceRemoved(resource, resourceProperties);
+	}
+
+	public void handleResourceRemoved(URL resource, Dictionary resourceProperties) {
         if (m_trackedResource == null || m_trackedResource.equals(resource)) {
     		long counter;
     		Object[] services;
     		synchronized (this) {
+    			m_resourceProperties.remove(m_resources.indexOf(resource));
     		    m_resources.remove(resource);
     			counter = m_resources.size();
     			services = m_services.toArray();
@@ -177,36 +210,50 @@
                 if (counter == 0) {
                     ds.dependencyUnavailable(this);
                     if (!isRequired()) {
-                        invokeRemoved(ds, resource);
+                        invokeRemoved(ds, resource, resourceProperties);
                     }
                 }
                 else {
                     ds.dependencyChanged(this);
-                    invokeRemoved(ds, resource);
+                    invokeRemoved(ds, resource, resourceProperties);
                 }
             }
         }
 	}
 	
-    public void invokeAdded(DependencyService ds, URL serviceInstance) {
-        invoke(ds, serviceInstance, m_callbackAdded);
+    public void invokeAdded(DependencyService ds, URL serviceInstance, Dictionary resourceProperties) {
+        invoke(ds, serviceInstance, resourceProperties, m_callbackAdded);
     }
 
-    public void invokeChanged(DependencyService ds, URL serviceInstance) {
-        invoke(ds, serviceInstance, m_callbackChanged);
+    public void invokeChanged(DependencyService ds, URL serviceInstance, Dictionary resourceProperties) {
+    	invoke(ds, serviceInstance, resourceProperties, m_callbackChanged);
     }
 
-    public void invokeRemoved(DependencyService ds, URL serviceInstance) {
-        invoke(ds, serviceInstance, m_callbackRemoved);
+    public void invokeRemoved(DependencyService ds, URL serviceInstance, Dictionary resourceProperties) {
+    	invoke(ds, serviceInstance, resourceProperties, m_callbackRemoved);
     }
     
-    private void invoke(DependencyService ds, URL serviceInstance, String name) {
-        if (name != null) {
-            ds.invokeCallbackMethod(getCallbackInstances(ds), name,
-                new Class[][] {{ Component.class, URL.class }, { Component.class, Object.class }, { Component.class },  { URL.class }, { Object.class }, {}},
-                new Object[][] {{ ds.getServiceInterface(), serviceInstance }, { ds.getServiceInterface(), serviceInstance }, { ds.getServiceInterface() }, { serviceInstance }, { serviceInstance }, {}}
-            );
-        }
+    private void invoke(DependencyService ds, URL serviceInstance, Dictionary resourceProperties, String name) {
+    	if (name != null) {
+	        ds.invokeCallbackMethod(getCallbackInstances(ds), name,
+	                new Class[][] {
+	        				{ Component.class, URL.class, Dictionary.class }, 
+	        				{ Component.class, URL.class },
+	        				{ Component.class },  
+	        				{ URL.class, Dictionary.class }, 
+	        				{ URL.class },
+	        				{ Object.class }, 
+	        				{}},
+	                new Object[][] {
+	        				{ ds.getServiceInterface(), serviceInstance, resourceProperties }, 
+	        				{ ds.getServiceInterface(), serviceInstance }, 
+	        				{ ds.getServiceInterface() }, 
+	        				{ serviceInstance, resourceProperties },
+	        				{ serviceInstance },
+	        				{ serviceInstance }, 
+	        				{}}
+	            );
+    	}
     }
     
     /**
@@ -338,6 +385,17 @@
 		m_resourceFilter = resourceFilter;
 		return this;
 	}
+	
+	public ResourceDependency setFilter(String resourceFilter, String resourcePropertiesFilter) {
+        ensureNotActive();
+        m_resourceFilter = resourceFilter;
+		return this;
+	}
+	
+	public void setResourcePropertiesConfigurationMember() {
+		
+	}
+	
     public synchronized boolean isAutoConfig() {
         return m_autoConfig;
     }
@@ -355,6 +413,15 @@
         }
     }
     
+    private Dictionary lookupResourceProperties() {
+    	try {
+    		return (Dictionary) m_resourceProperties.get(0);
+    	}
+        catch (IndexOutOfBoundsException e) {
+            return null;
+        }    	
+    }
+    
     public Object getAutoConfigInstance() {
         return lookupResource();
     }
@@ -370,12 +437,14 @@
     public void invokeAdded(DependencyService service) {
         // we remember these for future reference, needed for required callbacks
         m_resourceInstance = lookupResource();
-        invokeAdded(service, m_resourceInstance);
+        m_resourcePropertiesInstance = lookupResourceProperties();
+        invokeAdded(service, m_resourceInstance, m_resourcePropertiesInstance);
     }
 
     public void invokeRemoved(DependencyService service) {
-        invokeRemoved(service, m_resourceInstance);
+        invokeRemoved(service, m_resourceInstance, m_resourcePropertiesInstance);
         m_resourceInstance = null;
+        m_resourcePropertiesInstance = null;
     }
 
     public ResourceDependency setPropagate(boolean propagate) {
@@ -393,6 +462,7 @@
     
     public Dictionary getProperties() {
         URL resource = lookupResource();
+        Dictionary resourceProperties = lookupResourceProperties();
         if (resource != null) {
             if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
                 try {
@@ -412,6 +482,21 @@
                 props.setProperty(ResourceHandler.PATH, resource.getPath());
                 props.setProperty(ResourceHandler.PROTOCOL, resource.getProtocol());
                 props.setProperty(ResourceHandler.PORT, Integer.toString(resource.getPort()));
+                // add the custom resource properties
+                if (resourceProperties != null) {
+                	Enumeration properyKeysEnum = resourceProperties.keys(); 
+                	while (properyKeysEnum.hasMoreElements()) {
+                		String key = (String) properyKeysEnum.nextElement();
+                		if (!key.equals(ResourceHandler.HOST) &&
+                				!key.equals(ResourceHandler.PATH) &&
+                				!key.equals(ResourceHandler.PROTOCOL) &&
+                				!key.equals(ResourceHandler.PORT)) {
+                			props.setProperty(key, resourceProperties.get(key).toString());
+                		} else {
+                			m_logger.log(LogService.LOG_WARNING, "Custom resource property is overlapping with the default resource property for key: " + key);
+                		}
+                	}
+                }
                 return props;
             }
         }