felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pde...@apache.org
Subject svn commit: r1564995 [5/17] - in /felix/sandbox/pderop/dependencymanager: ./ core/ core/.externalToolBuilders/ core/.settings/ core/src/ core/src/main/ core/src/main/java/ core/src/main/java/org/ core/src/main/java/org/apache/ core/src/main/java/org/ap...
Date Wed, 05 Feb 2014 23:22:36 GMT
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java Wed Feb  5 23:22:32 2014
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl;
+
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ComponentStateListener;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ResourceDependency;
+
+/**
+ * Resource adapter service implementation. This class extends the FilterService in order to catch
+ * some Service methods for configuring actual resource adapter service implementation.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ResourceAdapterServiceImpl extends FilterService {
+    private Object m_callbackInstance = null;
+    private String m_callbackChanged = "changed";
+    private String m_callbackAdded = "setResource";
+    private final String m_resourceFilter;
+    
+    /**
+     * 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 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_resourceFilter = resourceFilter;
+        m_component.setImplementation(new ResourceAdapterImpl(propagate))
+            .add(dm.createResourceDependency()
+                 .setFilter(resourceFilter)
+                 .setAutoConfig(false)
+                 .setCallbacks("added", "removed"))
+            .setCallbacks("init", null, "stop", null);
+    }
+    
+    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_resourceFilter = resourceFilter;
+        m_component.setImplementation(new ResourceAdapterImpl(propagateCallbackInstance, propagateCallbackMethod))
+            .add(dm.createResourceDependency()
+                 .setFilter(resourceFilter)
+                 .setAutoConfig(false)
+                 .setCallbacks("added", "removed"))
+            .setCallbacks("init", null, "stop", null);
+    }   
+    
+    public String getName() {
+        return "Resource Adapter" + ((m_resourceFilter != null) ? " with filter " + m_resourceFilter : "");
+    }
+
+    public class ResourceAdapterImpl extends AbstractDecorator {
+        private final boolean m_propagate;
+        private final Object m_propagateCallbackInstance;
+        private final String m_propagateCallbackMethod;
+
+        public ResourceAdapterImpl(boolean propagate) {
+            this(propagate, null, null);
+        }
+
+        public ResourceAdapterImpl(Object propagateCallbackInstance, String propagateCallbackMethod) {
+            this(true, propagateCallbackInstance, propagateCallbackMethod);
+        }
+        
+        private ResourceAdapterImpl(boolean propagate, Object propagateCallbackInstance, String propagateCallbackMethod) {
+            m_propagate = propagate;
+            m_propagateCallbackInstance = propagateCallbackInstance;
+            m_propagateCallbackMethod = propagateCallbackMethod;
+        }
+
+        public Component createService(Object[] properties) {
+            URL resource = (URL) properties[0]; 
+            Properties props = new Properties();
+            if (m_serviceProperties != null) {
+                Enumeration e = m_serviceProperties.keys();
+                while (e.hasMoreElements()) {
+                    Object key = e.nextElement();
+                    props.put(key, m_serviceProperties.get(key));
+                }
+            }
+            List dependencies = m_component.getDependencies();
+            // the first dependency is always the dependency on the resource, which
+            // will be replaced with a more specific dependency below
+            dependencies.remove(0);
+            ResourceDependency resourceDependency = m_manager.createResourceDependency()
+                 .setResource(resource)
+                 .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);
+            } else {
+                resourceDependency.setPropagate(m_propagate);
+            }
+            Component service = m_manager.createComponent()
+                .setInterface(m_serviceInterfaces, props)
+                .setImplementation(m_serviceImpl)
+                .setFactory(m_factory, m_factoryCreateMethod) // if not set, no effect
+                .setComposition(m_compositionInstance, m_compositionMethod) // if not set, no effect
+                .setCallbacks(m_callbackObject, m_init, m_start, m_stop, m_destroy) // if not set, no effect
+                .add(resourceDependency);
+            
+            configureAutoConfigState(service, m_component);
+
+            for (int i = 0; i < dependencies.size(); i++) {
+                service.add(((Dependency) dependencies.get(i)).createCopy());
+            }
+
+            for (int i = 0; i < m_stateListeners.size(); i ++) {
+                service.addStateListener((ComponentStateListener) m_stateListeners.get(i));
+            }
+            return service;
+        }
+    }
+}

Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/SerialExecutor.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/SerialExecutor.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/SerialExecutor.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/SerialExecutor.java Wed Feb  5 23:22:32 2014
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl;
+
+import java.util.LinkedList;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * Allows you to enqueue tasks from multiple threads and then execute
+ * them on one thread sequentially. It assumes more than one thread will
+ * try to execute the tasks and it will make an effort to pick the first
+ * task that comes along whilst making sure subsequent tasks return
+ * without waiting.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public final class SerialExecutor {
+	private static final Runnable DUMMY_RUNNABLE = new Runnable() { public void run() {}; };
+    private final LinkedList m_workQueue = new LinkedList();
+    private Runnable m_active;
+    private volatile Thread m_runningThread;
+    private final Logger m_logger;
+    
+    /**
+     * Makes a new SerialExecutor
+     * @param logger the logger used to log possible errors thrown by submitted tasks.
+     */
+    public SerialExecutor(Logger logger) {
+        m_logger = logger;
+    }
+    
+    /**
+     * Enqueue a new task for later execution. This method is
+     * thread-safe, so multiple threads can contribute tasks.
+     * 
+     * @param runnable the runnable containing the actual task
+     */
+    public synchronized void enqueue(final Runnable runnable) {
+    	m_workQueue.addLast(new Runnable() {
+			public void run() {
+				try {
+					runnable.run();
+				}
+				catch (Throwable t) {
+		            m_logger.log(LogService.LOG_ERROR, "got unexpected exception while executing dependencymanager task:"
+		                + toString(), t);
+				}
+				finally {
+					scheduleNext();
+				}
+			}
+		});
+    }
+    
+    /**
+     * Execute any pending tasks. This method is thread safe,
+     * so multiple threads can try to execute the pending
+     * tasks, but only the first will be used to actually do
+     * so. Other threads will return immediately.
+     */
+    public void execute() {
+    	Runnable active;
+    	synchronized (this) {
+    		active = m_active;
+    		// for now just put some non-null value in there so we can never
+    		// get a race condition when two threads enter this section after
+    		// one another (causing sheduleNext() to be invoked twice below)
+    		m_active = DUMMY_RUNNABLE;
+    	}
+    	if (active == null) {
+    	    scheduleNext();
+    	}
+    }
+    
+    /**
+     * Execute a task. This method is thread safe,
+     * so multiple threads can try to execute a task
+     * but only the first will be executed, other threads will return immediately, and the
+     * first thread will execute the tasks scheduled by the other threads.
+     */
+    public void execute(Runnable task) {
+        enqueue(task);
+        execute();
+    }
+    
+    /**
+     * Immediately execute a task if the current thread is being executed from that executor, else 
+     * enqueue the task and try to execute it (same behavior as if the task would have been enqueued / executed).
+     */
+    public void executeNow(Runnable task) {
+        if (Thread.currentThread() == (Thread) m_runningThread) {
+            task.run();
+        } else {
+           enqueue(task);
+           execute();
+        }
+    }
+
+    private void scheduleNext() {
+    	Runnable active;
+    	synchronized (this) {
+			if (!m_workQueue.isEmpty()) {
+			    m_runningThread = Thread.currentThread();
+				m_active = (Runnable) m_workQueue.removeFirst();
+			} else {
+	            m_runningThread = null;
+			    m_active = null;
+			}
+    		active = m_active;
+    	}
+    	if (active != null) {
+            active.run();
+        }
+    }
+}

Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceRegistrationImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceRegistrationImpl.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceRegistrationImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceRegistrationImpl.java Wed Feb  5 23:22:32 2014
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl;
+
+import java.util.Dictionary;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * A wrapper around a service registration that blocks until the
+ * service registration is available.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public final class ServiceRegistrationImpl implements ServiceRegistration {
+    public static final ServiceRegistrationImpl ILLEGAL_STATE = new ServiceRegistrationImpl();
+    private volatile ServiceRegistration m_registration;
+
+    public ServiceRegistrationImpl() {
+        m_registration = null;
+    }
+    
+    public ServiceReference getReference() {
+        return ensureRegistration().getReference();
+    }
+
+    public void setProperties(Dictionary dictionary) {
+        ensureRegistration().setProperties(dictionary);
+    }
+
+    public void unregister() {
+        ensureRegistration().unregister();
+    }
+
+    public boolean equals(Object obj) {
+        return ensureRegistration().equals(obj);
+    }
+
+    public int hashCode() {
+        return ensureRegistration().hashCode();
+    }
+
+    public String toString() {
+        return ensureRegistration().toString();
+    }
+    
+    private synchronized ServiceRegistration ensureRegistration() {
+        while (m_registration == null) {
+            try {
+                wait();
+            }
+            catch (InterruptedException ie) {
+                // we were interrupted so hopefully we will now have a
+                // service registration ready; if not we wait again
+            }
+        }
+        // check if we're in an illegal state and throw an exception
+        if (ILLEGAL_STATE == m_registration) {
+            throw new IllegalStateException("Service is not registered.");
+        }
+        return m_registration;
+    }
+
+    /**
+     * Sets the service registration and notifies all waiting parties.
+     */
+    void setServiceRegistration(ServiceRegistration registration) {
+        synchronized (this) {
+        	m_registration = registration;
+            notifyAll();
+        }
+    }
+
+    /**
+     * Sets this wrapper to an illegal state, which will cause all threads
+     * that are waiting for this service registration to fail.
+     */
+	void setIllegalState() {
+        setServiceRegistration(ServiceRegistrationImpl.ILLEGAL_STATE);
+	}
+}

Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/State.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/State.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/State.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/State.java Wed Feb  5 23:22:32 2014
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl;
+
+import java.util.List;
+
+import org.apache.felix.dm.Dependency;
+
+/**
+ * Encapsulates the current state of the dependencies of a service. A state is
+ * basically an immutable value object.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public final class State {
+    private static final String[] STATES = { "?", "inactive", "waiting for required", "tracking optional", "bound", "waiting for required (instantiated)" };
+    private static final int INACTIVE = 1;
+    private static final int WAITING_FOR_REQUIRED = 2;
+    private static final int TRACKING_OPTIONAL = 3;
+    private static final int BOUND = 4;
+    private static final int WAITING_FOR_REQUIRED_INSTANTIATED = 5;
+    private final List m_deps;
+    private final int m_state;
+    private String m_stringValue;
+    
+    /**
+     * Creates a new state instance.
+     * 
+     * @param deps the dependencies that determine the state
+     * @param isActive <code>true</code> if the service is active (started)
+     */
+    public State(List deps, boolean isActive, boolean isInstantiated, boolean isBound /* unused? */) {
+        m_deps = deps;
+        // only bother calculating dependencies if we're active
+        if (isActive) {
+            boolean allRequiredAvailable = true;
+            boolean keepInstanceAround = isInstantiated;
+            for (int i = 0; i < deps.size(); i++) {
+                Dependency dep = (Dependency) deps.get(i);
+                if (dep.isRequired()) {
+                    if (!dep.isAvailable()) {
+                        allRequiredAvailable = false;
+                        if (!dep.isInstanceBound()) {
+                            keepInstanceAround = false;
+                        }
+                    }
+                }
+            }
+            if (allRequiredAvailable) {
+                if (isInstantiated) {
+                    m_state = BOUND;
+                }
+                else {
+                    m_state = TRACKING_OPTIONAL;
+                }
+            }
+            else {
+                if (keepInstanceAround) {
+                    m_state = WAITING_FOR_REQUIRED_INSTANTIATED;
+                }
+                else {
+                    m_state = WAITING_FOR_REQUIRED;
+                }
+            }
+        }
+        else {
+            m_state = INACTIVE;
+        }
+    }
+    
+    public boolean isInactive() {
+        return m_state == INACTIVE;
+    }
+    
+    public boolean isWaitingForRequired() {
+        return m_state == WAITING_FOR_REQUIRED;
+    }
+    
+    public boolean isTrackingOptional() {
+        return m_state == TRACKING_OPTIONAL;
+    }
+    
+    public boolean isBound() {
+        return m_state == BOUND;
+    }
+    
+    public boolean isAllRequiredAvailable() {
+        return isTrackingOptional() || isBound();
+    }
+    
+    public boolean isWaitingForRequiredInstantiated() {
+        return m_state == WAITING_FOR_REQUIRED_INSTANTIATED;
+    }
+    
+    public List getDependencies() {
+        return m_deps;
+    }
+    
+    public synchronized String toString() {
+        if (m_stringValue == null) {
+            // we only need to determine this once, but we do it lazily
+            StringBuffer buf = new StringBuffer();
+            buf.append("State[" + STATES[m_state]);
+            List deps = m_deps;
+            for (int i = 0; i < deps.size(); i++) {
+                if (i == 0) {
+                    buf.append("|");
+                }
+                Dependency dep = (Dependency) deps.get(i);
+                buf.append("(" + (dep.isRequired() ? "Req " : "   ") + (dep.isAvailable() ? "Avl " : "    ") + (dep.isInstanceBound() ? "InB " : "    ") + (dep.isPropagated() ? "Prp " : "    ") + dep + ")");
+            }
+            buf.append("]");
+            m_stringValue = buf.toString();
+        }
+        return m_stringValue;
+    }
+}

Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java Wed Feb  5 23:22:32 2014
@@ -0,0 +1,501 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl.dependencies;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.dm.BundleDependency;
+import org.apache.felix.dm.ComponentDependencyDeclaration;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyService;
+import org.apache.felix.dm.InvocationUtil;
+import org.apache.felix.dm.impl.DefaultNullObject;
+import org.apache.felix.dm.impl.Logger;
+import org.apache.felix.dm.tracker.BundleTracker;
+import org.apache.felix.dm.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;
+import org.osgi.service.log.LogService;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class BundleDependencyImpl extends DependencyBase implements BundleDependency, BundleTrackerCustomizer, ComponentDependencyDeclaration {
+	private final BundleContext m_context;
+	private BundleTracker m_tracker;
+	private int m_stateMask = Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE;
+	private List m_services = new ArrayList();
+	private boolean m_isAvailable;
+    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;
+	private String m_autoConfigInstance;
+    private Object m_nullObject;
+    private boolean m_autoConfigInvoked;
+    private boolean m_propagate;
+    private Object m_propagateCallbackInstance;
+    private String m_propagateCallbackMethod;
+
+    public BundleDependencyImpl(BundleContext context, Logger logger) {
+        super(logger);
+		m_context = context;
+		m_autoConfig = true;
+	}
+    
+    public BundleDependencyImpl(BundleDependencyImpl prototype) {
+        super(prototype);
+        m_context = prototype.m_context;
+        m_autoConfig = prototype.m_autoConfig;
+        m_stateMask = prototype.m_stateMask;
+        m_nullObject = prototype.m_nullObject;
+        m_bundleInstance = prototype.m_bundleInstance;
+        m_filter = prototype.m_filter;
+        m_bundleId = prototype.m_bundleId;
+        m_propagate = prototype.m_propagate;
+        m_callbackInstance = prototype.m_callbackInstance;
+        m_callbackAdded = prototype.m_callbackAdded;
+        m_callbackChanged = prototype.m_callbackChanged;
+        m_callbackRemoved = prototype.m_callbackRemoved;
+        m_autoConfigInstance = prototype.m_autoConfigInstance;
+    }
+    
+    public Dependency createCopy() {
+        return new BundleDependencyImpl(this);
+    }
+
+    public BundleDependency setInstanceBound(boolean isInstanceBound) {
+        setIsInstanceBound(isInstanceBound);
+        return this;
+    }
+    
+	public synchronized boolean isAvailable() {
+        return m_isAvailable;
+    }
+
+    public void start(DependencyService service) {
+        boolean needsStarting = false;
+		synchronized (this) {
+		    m_services.add(service);
+		    if (!m_isStarted) {
+    			m_tracker = new BundleTracker(m_context, m_stateMask, this);
+    			m_isStarted = true;
+    			needsStarting = true;
+		    }
+		}
+		if (needsStarting) {
+		    m_tracker.open();
+		}
+	}
+
+	public void stop(DependencyService service) {
+	    boolean needsStopping = false;
+        synchronized (this) {
+            if (m_services.size() == 1 && m_services.contains(service)) {
+                m_isStarted = false;
+                needsStopping = true;
+            }
+        }
+        if (needsStopping) {
+            m_tracker.close();
+            m_tracker = null;
+            m_services.remove(service);
+        }            
+	}
+
+	public String getName() {
+        StringBuilder sb = new StringBuilder();
+        if ((m_stateMask & Bundle.ACTIVE) != 0) {
+            sb.append("active ");
+        }
+        if ((m_stateMask & Bundle.INSTALLED) != 0) {
+            sb.append("installed ");
+        }
+        if ((m_stateMask & Bundle.RESOLVED) != 0) {
+            sb.append("resolved ");
+        }
+        if (m_filter != null) {
+            sb.append(m_filter.toString());
+        }
+        if (m_bundleId != -1) {
+            sb.append("bundle.id=" + m_bundleId);
+        }
+        return sb.toString();
+	}
+
+	public String getType() {
+		return "bundle";
+	}
+
+	public Object addingBundle(Bundle bundle, BundleEvent event) {
+		// if we don't like a bundle, we could reject it here by returning null
+		long bundleId = bundle.getBundleId();
+        if (m_bundleId >= 0 && m_bundleId != bundleId) {
+			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) {
+	    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, bundle);
+	            }
+	        }
+	        else {
+	            ds.dependencyChanged(this);
+	            invokeAdded(ds, bundle);
+	        }
+	    }
+	}
+
+	public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+		Object[] services = m_services.toArray();
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            ds.dependencyChanged(this);
+            if (ds.isInstantiated()) {
+                invokeChanged(ds, bundle);
+            }
+        }
+	}
+
+	public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+		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, bundle);
+                }
+            }
+            else {
+                ds.dependencyChanged(this);
+                invokeRemoved(ds, bundle);
+            }
+        }
+	}
+	
+    private synchronized boolean makeAvailable() {
+        if (!isAvailable()) {
+            m_isAvailable = true;
+            return true;
+        }
+        return false;
+    }
+    
+    private synchronized boolean makeUnavailable() {
+        if ((isAvailable()) && (m_tracker.getTrackingCount() == 0)) {
+            m_isAvailable = false;
+            return true;
+        }
+        return false;
+    }
+    
+    public void invokeAdded(DependencyService dependencyService, Bundle service) {
+        invoke(dependencyService, service, m_callbackAdded);
+    }
+
+    public void invokeChanged(DependencyService dependencyService, Bundle service) {
+        invoke(dependencyService, service, m_callbackChanged);
+    }
+    
+    public void invokeRemoved(DependencyService dependencyService, Bundle service) {
+        invoke(dependencyService, service, m_callbackRemoved);
+    }
+    
+    public void invoke(DependencyService dependencyService, Bundle service, String name) {
+        if (name != null) {
+            dependencyService.invokeCallbackMethod(getCallbackInstances(dependencyService), name,
+              new Class[][] {{Bundle.class}, {Object.class}, {}},
+              new Object[][] {{service}, {service}, {}}
+            );
+        }
+    }
+
+    private synchronized Object[] getCallbackInstances(DependencyService dependencyService) {
+        if (m_callbackInstance == null) {
+            return dependencyService.getCompositionInstances();
+        }
+        else {
+            return new Object[] { m_callbackInstance };
+        }
+    }
+    
+    /**
+     * 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) && ! m_autoConfigInvoked) {
+            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;
+        m_autoConfigInvoked = true;
+        return this;
+    }
+
+    public synchronized BundleDependency setAutoConfig(String instanceName) {
+        ensureNotActive();
+        m_autoConfig = (instanceName != null);
+        m_autoConfigInstance = instanceName;
+        m_autoConfigInvoked = true;
+        return this;
+    }
+    
+    public synchronized BundleDependency setRequired(boolean required) {
+        ensureNotActive();
+        setIsRequired(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;
+    }
+
+    public Object getAutoConfigInstance() {
+        return lookupBundle();
+    }
+
+    public Bundle lookupBundle() {
+        Bundle service = null;
+        if (m_isStarted) {
+            service = getBundle();
+        }
+        else {
+            Bundle[] bundles = m_context.getBundles();
+            for (int i = 0; i < bundles.length; i++) {
+                if ((bundles[i].getState() & m_stateMask) > 0) {
+                    Filter filter = m_filter;
+                    if (filter == null) {
+                        service = bundles[i];
+                        break;
+                    }
+                    else if (filter.match(bundles[i].getHeaders())) {
+                        service = bundles[i];
+                        break;
+                    }
+                }
+            }
+        }
+        if (service == null && isAutoConfig()) {
+            // TODO does it make sense to add support for custom bundle impls?
+//            service = getDefaultImplementation();
+            if (service == null) {
+                service = getNullObject();
+            }
+        }
+        return service;
+    }
+
+    private Bundle getNullObject() {
+        if (m_nullObject == null) {
+            try {
+                m_nullObject = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { Bundle.class }, new DefaultNullObject()); 
+            }
+            catch (Exception e) {
+                m_logger.log(Logger.LOG_ERROR, "Could not create null object for Bundle.", e);
+            }
+        }
+        return (Bundle) m_nullObject;
+    }
+    
+    public String getAutoConfigName() {
+        return m_autoConfigInstance;
+    }
+
+    public Class getAutoConfigType() {
+        return Bundle.class;
+    }
+
+    public void invokeAdded(DependencyService service) {
+        // we remember these for future reference, needed for required service callbacks
+        m_bundleInstance = lookupBundle();
+        invokeAdded(service, m_bundleInstance);
+    }
+
+    public void invokeRemoved(DependencyService service) {
+        invokeRemoved(service, m_bundleInstance);
+        m_bundleInstance = null;
+    }
+    
+    public BundleDependency setPropagate(boolean propagate) {
+        ensureNotActive();
+        m_propagate = propagate;
+        return this;
+    }
+    
+    public BundleDependency setPropagate(Object instance, String method) {
+        setPropagate(instance != null && method != null);
+        m_propagateCallbackInstance = instance;
+        m_propagateCallbackMethod = method;
+        return this;
+    }
+    
+    public Dictionary getProperties() {
+        Bundle bundle = lookupBundle();
+        if (bundle != null) {
+            if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
+                try {
+                    return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ Bundle.class }}, new Object[][] {{ bundle }});
+                }
+                catch (InvocationTargetException e) {
+                    m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
+                }
+                catch (Exception e) {
+                    m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
+                }
+                throw new IllegalStateException("Could not invoke callback");
+            }
+            else {
+                return bundle.getHeaders();
+            }
+        }
+        else {
+            throw new IllegalStateException("cannot find bundle");
+        }
+    }
+
+    public boolean isPropagated() {
+        return m_propagate;
+    }
+}

Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java Wed Feb  5 23:22:32 2014
@@ -0,0 +1,420 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl.dependencies;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.felix.dm.ComponentDependencyDeclaration;
+import org.apache.felix.dm.ConfigurationDependency;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyActivation;
+import org.apache.felix.dm.DependencyService;
+import org.apache.felix.dm.InvocationUtil;
+import org.apache.felix.dm.PropertyMetaData;
+import org.apache.felix.dm.impl.Logger;
+import org.apache.felix.dm.impl.SerialExecutor;
+import org.apache.felix.dm.impl.metatype.MetaTypeProviderImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.log.LogService;
+
+/**
+ * Configuration dependency that can track the availability of a (valid) configuration.
+ * To use it, specify a PID for the configuration. The dependency is always required,
+ * because if it is not, it does not make sense to use the dependency manager. In that
+ * scenario, simply register your service as a <code>ManagedService(Factory)</code> and
+ * handle everything yourself. Also, only managed services are supported, not factories.
+ * There are a couple of things you need to be aware of when implementing the
+ * <code>updated(Dictionary)</code> method:
+ * <ul>
+ * <li>Make sure it throws a <code>ConfigurationException</code> when you get a
+ * configuration that is invalid. In this case, the dependency will not change:
+ * if it was not available, it will still not be. If it was available, it will
+ * remain available and implicitly assume you keep working with your old
+ * configuration.</li>
+ * <li>This method will be called before all required dependencies are available.
+ * Make sure you do not depend on these to parse your settings.</li>
+ * </ul>
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ConfigurationDependencyImpl extends DependencyBase implements ConfigurationDependency, ManagedService, ComponentDependencyDeclaration, DependencyActivation
+{
+    private BundleContext m_context;
+    private String m_pid;
+    private ServiceRegistration m_registration;
+    protected List m_services = new ArrayList();
+    private Dictionary m_settings;
+    private String m_callback;
+    private final Set m_updateInvokedCache = new HashSet();
+    private MetaTypeProviderImpl m_metaType;
+    private boolean m_propagate;
+    private Object m_propagateCallbackInstance;
+    private String m_propagateCallbackMethod;
+    private final SerialExecutor m_serial;
+    final DependencyService[] DEPENDENCY_SERVICE_TYPE = new DependencyService[0];
+
+    public ConfigurationDependencyImpl(BundleContext context, Logger logger) {
+        super(logger);
+        m_context = context;
+        m_serial = new SerialExecutor(logger);
+    }
+
+    public ConfigurationDependencyImpl(ConfigurationDependencyImpl prototype) {
+        super(prototype);
+        m_context = prototype.m_context;
+        m_pid = prototype.m_pid;
+        m_propagate = prototype.m_propagate;
+        m_callback = prototype.m_callback;
+        m_propagateCallbackInstance = prototype.m_propagateCallbackInstance;
+        m_propagateCallbackMethod = prototype.m_propagateCallbackMethod;
+        m_metaType = prototype.m_metaType;
+        m_serial = new SerialExecutor(prototype.m_logger);
+    }
+
+    public Dependency createCopy() {
+        return new ConfigurationDependencyImpl(this);
+    }
+
+    public synchronized boolean isAvailable() {
+        return m_settings != null;
+    }
+
+    /**
+     * Will always return <code>true</code> as optional configuration dependencies
+     * do not make sense. You might as well just implement <code>ManagedService</code>
+     * yourself in those cases.
+     */
+    public boolean isRequired() {
+        return true;
+    }
+
+    /**
+     * Returns <code>true</code> when configuration properties should be propagated
+     * as service properties.
+     */
+    public boolean isPropagated() {
+        return m_propagate;
+    }
+
+    public ConfigurationDependency setInstanceBound(boolean isInstanceBound) {
+        setIsInstanceBound(isInstanceBound);
+        return this;
+    }
+
+    public Dictionary getConfiguration() {
+        return m_settings;
+    }
+
+    public void start(DependencyService service) {
+        boolean needsStarting = false;
+        synchronized (this) {
+            m_services.add(service);
+            if (!m_isStarted) {
+                m_isStarted = true;
+                needsStarting = true;
+            }
+        }
+        if (needsStarting) {
+            Properties props = new Properties();
+            props.put(Constants.SERVICE_PID, m_pid);
+            ManagedService ms = this;
+            if (m_metaType != null) {
+                ms = m_metaType;
+            }
+            m_registration = m_context.registerService(ManagedService.class.getName(), ms, props);
+        }
+    }
+
+    public void stop(DependencyService service) {
+        ServiceRegistration registration = null;
+
+        synchronized (this) {
+            if (m_services.size() == 1 && m_services.contains(service)) {
+                m_isStarted = false;
+                registration = m_registration;
+                m_registration = null;
+            }
+        }
+        if (registration != null) {
+            registration.unregister();
+        }
+        synchronized (this) {
+            m_services.remove(service);
+        }
+    }
+
+    public ConfigurationDependency setCallback(String callback) {
+        m_callback = callback;
+        return this;
+    }
+
+    public void updated(final Dictionary settings) throws ConfigurationException {
+        synchronized (m_updateInvokedCache) {
+            m_updateInvokedCache.clear();
+        }
+        Dictionary old = null;
+        synchronized (this) {
+            old = m_settings;
+        }
+        final Dictionary oldSettings = old;
+
+        if (oldSettings == null && settings == null) {
+            // CM has started but our configuration is not yet present in the CM database: ignore
+            return;
+        }
+
+        // Get a snapshot of current registered services.
+        DependencyService[] srvs;
+        synchronized (this) {
+            srvs = (DependencyService[]) m_services.toArray(DEPENDENCY_SERVICE_TYPE);
+        }
+        final DependencyService[] services = srvs;
+
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = services[i];
+            // if non-null settings come in, we have to instantiate the service and
+            // apply these settings
+            ds.initService();
+            Object service = ds.getService();
+
+            if (service != null) {
+                invokeUpdate(ds, service, settings);
+            }
+            else {
+                m_logger.log(Logger.LOG_ERROR, "Service " + ds + " with configuration dependency " + this
+                    + " could not be instantiated.");
+                return;
+            }
+        }
+
+        synchronized (this) {
+            m_settings = settings;
+        }
+
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = services[i];
+            // If these settings did not cause a configuration exception, we determine if they have 
+            // caused the dependency state to change
+            if ((oldSettings == null) && (settings != null)) {
+                ds.dependencyAvailable(ConfigurationDependencyImpl.this);
+            }
+            if ((oldSettings != null) && (settings == null)) {
+                ds.dependencyUnavailable(ConfigurationDependencyImpl.this);
+            }
+            if ((oldSettings != null) && (settings != null)) {
+                ds.dependencyChanged(ConfigurationDependencyImpl.this);
+            }
+        }
+    }
+
+    private void invokeUpdate(DependencyService ds, Object service, Dictionary settings) throws ConfigurationException {
+        boolean wasAdded;
+        synchronized (m_updateInvokedCache) {
+            wasAdded = m_updateInvokedCache.add(ds);
+        }
+        if (wasAdded) {
+            String callback = (m_callback == null) ? "updated" : m_callback;
+            try {
+                // if exception is thrown here, what does that mean for the
+                // state of this dependency? how smart do we want to be??
+                // it's okay like this, if the new settings contain errors, we
+                // remain in the state we were, assuming that any error causes
+                // the "old" configuration to stay in effect.
+                // CM will log any thrown exceptions.
+                InvocationUtil.invokeCallbackMethod(service, callback, new Class[][] { { Dictionary.class } },
+                    new Object[][] { { settings } });
+            }
+            catch (InvocationTargetException e) {
+                // The component has thrown an exception during it's callback invocation.
+                if (e.getTargetException() instanceof ConfigurationException) {
+                    // the callback threw an OSGi ConfigurationException: just re-throw it.
+                    throw (ConfigurationException) e.getTargetException();
+                }
+                else {
+                    // wrap the callback exception into a ConfigurationException.
+                    throw new ConfigurationException(null, "Service " + ds + " with " + this.toString()
+                        + " could not be updated", e.getTargetException());
+                }
+            }
+            catch (NoSuchMethodException e) {
+                // if the method does not exist, ignore it
+            }
+            catch (Throwable t) {
+                // wrap any other exception as a ConfigurationException.
+                throw new ConfigurationException(null, "Service " + ds + " with " + this.toString()
+                    + " could not be updated", t);
+            }
+        }
+    }
+
+    /**
+     * Sets the <code>service.pid</code> of the configuration you
+     * are depending on.
+     */
+    public ConfigurationDependency setPid(String pid) {
+        ensureNotActive();
+        m_pid = pid;
+        return this;
+    }
+
+    /**
+     * Sets propagation of the configuration properties to the service
+     * properties. Any additional service properties specified directly
+     * are merged with these.
+     */
+    public ConfigurationDependency setPropagate(boolean propagate) {
+        ensureNotActive();
+        m_propagate = propagate;
+        return this;
+    }
+
+    private synchronized void ensureNotActive() {
+        if (m_services != null && m_services.size() > 0) {
+            throw new IllegalStateException("Cannot modify state while active.");
+        }
+    }
+
+    public String toString() {
+        return "ConfigurationDependency[" + m_pid + "]";
+    }
+
+    public String getName() {
+        return m_pid;
+    }
+
+    public String getType() {
+        return "configuration";
+    }
+
+    public Object getAutoConfigInstance() {
+        return getConfiguration();
+    }
+
+    public String getAutoConfigName() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Class getAutoConfigType() {
+        return Dictionary.class;
+    }
+
+    public void invokeAdded(DependencyService service) {
+        try {
+            invokeUpdate(service, service.getService(), getConfiguration());
+        }
+        catch (ConfigurationException e) {
+            // if this happens, it's definitely an inconsistency, since we
+            // asked the instance the same question before (if this is a
+            // valid configuration) and then it was
+            e.printStackTrace();
+        }
+    }
+
+    public void invokeRemoved(DependencyService service) {
+        synchronized (m_updateInvokedCache) {
+            m_updateInvokedCache.remove(service);
+        }
+    }
+
+    public boolean isAutoConfig() {
+        return false;
+    }
+
+    public ConfigurationDependency setPropagate(Object instance, String method) {
+        setPropagate(instance != null && method != null);
+        m_propagateCallbackInstance = instance;
+        m_propagateCallbackMethod = method;
+        return this;
+    }
+
+    public Dictionary getProperties() {
+        Dictionary config = getConfiguration();
+        if (config != null) {
+            if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
+                try {
+                    return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance,
+                        m_propagateCallbackMethod, new Class[][] { { Dictionary.class }, {} }, new Object[][] {
+                                { config }, {} });
+                }
+                catch (InvocationTargetException e) {
+                    m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
+                }
+                catch (Exception e) {
+                    m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
+                }
+                throw new IllegalStateException("Could not invoke callback");
+            }
+            else {
+                return config;
+            }
+        }
+        else {
+            throw new IllegalStateException("cannot find configuration");
+        }
+    }
+
+    public BundleContext getBundleContext() {
+        return m_context;
+    }
+
+    public Logger getLogger() {
+        return m_logger;
+    }
+
+    public ConfigurationDependency add(PropertyMetaData properties) {
+        createMetaTypeImpl();
+        m_metaType.add(properties);
+        return this;
+    }
+
+    public ConfigurationDependency setDescription(String description) {
+        createMetaTypeImpl();
+        m_metaType.setDescription(description);
+        return this;
+    }
+
+    public ConfigurationDependency setHeading(String heading) {
+        createMetaTypeImpl();
+        m_metaType.setName(heading);
+        return this;
+    }
+
+    public ConfigurationDependency setLocalization(String path) {
+        createMetaTypeImpl();
+        m_metaType.setLocalization(path);
+        return this;
+    }
+
+    private synchronized void createMetaTypeImpl() {
+        if (m_metaType == null) {
+            m_metaType = new MetaTypeProviderImpl(getName(), getBundleContext(), getLogger(), this, null);
+        }
+    }
+}

Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/DependencyBase.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/DependencyBase.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/DependencyBase.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/DependencyBase.java Wed Feb  5 23:22:32 2014
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl.dependencies;
+
+import org.apache.felix.dm.ComponentDependencyDeclaration;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyActivation;
+import org.apache.felix.dm.impl.Logger;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class DependencyBase implements Dependency, DependencyActivation {
+    private volatile boolean m_isRequired;
+    private volatile boolean m_isInstanceBound;
+    protected final Logger m_logger;
+    protected volatile boolean m_isStarted;
+
+    public DependencyBase(Logger logger) {
+        m_logger = logger;
+    }
+    
+    public DependencyBase(DependencyBase prototype) {
+        m_logger = prototype.m_logger;
+        m_isRequired = prototype.isRequired();
+        m_isInstanceBound = prototype.m_isInstanceBound;
+    }
+
+    public boolean isRequired() {
+        return m_isRequired;
+    }
+    
+    protected void setIsRequired(boolean isRequired) {
+        m_isRequired = isRequired;
+    }
+    
+    public final boolean isInstanceBound() {
+        return m_isInstanceBound;
+    }
+
+    public final void setIsInstanceBound(boolean isInstanceBound) {
+        m_isInstanceBound = isInstanceBound;
+    }
+    
+    public int getState() {
+        if (m_isStarted) {
+            return (isAvailable() ? 1 : 0) + (isRequired() ? 2 : 0);
+        }
+        else {
+            return isRequired() ? ComponentDependencyDeclaration.STATE_REQUIRED : ComponentDependencyDeclaration.STATE_OPTIONAL;
+        }
+    }
+
+}

Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java Wed Feb  5 23:22:32 2014
@@ -0,0 +1,535 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl.dependencies;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ComponentDependencyDeclaration;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyActivation;
+import org.apache.felix.dm.DependencyService;
+import org.apache.felix.dm.InvocationUtil;
+import org.apache.felix.dm.ResourceDependency;
+import org.apache.felix.dm.ResourceHandler;
+import org.apache.felix.dm.impl.Logger;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogService;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ResourceDependencyImpl extends DependencyBase implements ResourceDependency, ResourceHandler, DependencyActivation, ComponentDependencyDeclaration {
+	private volatile BundleContext m_context;
+	private volatile ServiceRegistration m_registration;
+    private Object m_callbackInstance;
+    private String m_callbackAdded;
+    private String m_callbackChanged;
+    private String m_callbackRemoved;
+    private boolean m_autoConfig;
+    private String m_autoConfigInstance;
+    protected List m_services = new ArrayList();
+	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;
+	
+    public ResourceDependencyImpl(BundleContext context, Logger logger) {
+        super(logger);
+    	m_context = context;
+    	m_autoConfig = true;
+    }
+    
+    public ResourceDependencyImpl(ResourceDependencyImpl prototype) {
+        super(prototype);
+        m_context = prototype.m_context;
+        m_autoConfig = prototype.m_autoConfig;
+        m_callbackInstance = prototype.m_callbackInstance;
+        m_callbackAdded = prototype.m_callbackAdded;
+        m_callbackChanged = prototype.m_callbackChanged;
+        m_callbackRemoved = prototype.m_callbackRemoved;
+        m_autoConfigInstance = prototype.m_autoConfigInstance;
+        m_resourceFilter = prototype.m_resourceFilter;
+        m_trackedResource = prototype.m_trackedResource;
+        m_propagate = prototype.m_propagate;
+    }
+    
+    public Dependency createCopy() {
+        return new ResourceDependencyImpl(this);
+    }
+    
+	public synchronized boolean isAvailable() {
+		return m_resources.size() > 0;
+	}
+
+	public void start(DependencyService service) {
+	    boolean needsStarting = false;
+	    synchronized (this) {
+	        m_services.add(service);
+	        if (!m_isStarted) {
+	            m_isStarted = true;
+	            needsStarting = true;
+	        }
+	    }
+	    if (needsStarting) {
+	        Dictionary props = null;
+	        if (m_trackedResource != null) {
+                props = new Properties();
+                props.put(ResourceHandler.URL, m_trackedResource);
+	        }
+	        else { 
+	        	if (m_resourceFilter != null) {
+		            props = new Properties();
+		            props.put(ResourceHandler.FILTER, m_resourceFilter);
+	        	}
+	        }
+	        m_registration = m_context.registerService(ResourceHandler.class.getName(), this, props);
+	    }
+	}
+
+	public void stop(DependencyService service) {
+	    boolean needsStopping = false;
+	    synchronized (this) {
+            if (m_services.size() == 1 && m_services.contains(service)) {
+                m_isStarted = false;
+                needsStopping = true;
+                m_services.remove(service);
+            }
+	    }
+	    if (needsStopping) {
+	        m_registration.unregister();
+	        m_registration = null;
+	    }
+	}
+
+	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();
+    		}
+            for (int i = 0; i < services.length; i++) {
+                DependencyService ds = (DependencyService) services[i];
+                if (counter == 1) {
+                    ds.dependencyAvailable(this);
+                    if (!isRequired()) {
+                        invokeAdded(ds, resource, resourceProperties);
+                    }
+                }
+                else {
+                    ds.dependencyChanged(this);
+                    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, 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) {
+    			if (m_resources.indexOf(resource) == -1) {
+    				m_logger.log(Logger.LOG_WARNING, "handleResourceRemoved called for unknown resource: " + resource);
+    				return;
+    			}
+    			m_resourceProperties.remove(m_resources.indexOf(resource));
+    		    m_resources.remove(resource);
+    			counter = m_resources.size();
+    			services = m_services.toArray();
+    		}
+            for (int i = 0; i < services.length; i++) {
+                DependencyService ds = (DependencyService) services[i];
+                if (counter == 0) {
+                    ds.dependencyUnavailable(this);
+                    if (!isRequired()) {
+                        invokeRemoved(ds, resource, resourceProperties);
+                    }
+                }
+                else {
+                    ds.dependencyChanged(this);
+                    invokeRemoved(ds, resource, resourceProperties);
+                }
+            }
+        }
+	}
+	
+    public void invokeAdded(DependencyService ds, URL serviceInstance, Dictionary resourceProperties) {
+        invoke(ds, serviceInstance, resourceProperties, m_callbackAdded);
+    }
+
+    public void invokeChanged(DependencyService ds, URL serviceInstance, Dictionary resourceProperties) {
+    	invoke(ds, serviceInstance, resourceProperties, m_callbackChanged);
+    }
+
+    public void invokeRemoved(DependencyService ds, URL serviceInstance, Dictionary resourceProperties) {
+    	invoke(ds, serviceInstance, resourceProperties, m_callbackRemoved);
+    }
+    
+    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 }, 
+	        				{}}
+	            );
+    	}
+    }
+    
+    /**
+     * 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 synchronized Object[] getCallbackInstances(DependencyService ds) {
+        if (m_callbackInstance == null) {
+            return ds.getCompositionInstances();
+        }
+        else {
+            return new Object[] { m_callbackInstance };
+        }
+    }
+
+	public ResourceDependency setResource(URL resource) {
+		m_trackedResource = resource;
+		return this;
+	}
+	
+    public synchronized ResourceDependency setRequired(boolean required) {
+        ensureNotActive();
+        setIsRequired(required);
+        return this;
+    }
+
+	public ResourceDependency setFilter(String resourceFilter) {
+        ensureNotActive();
+		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;
+    }
+    
+    public URL getResource() {
+    	return lookupResource();
+    }
+
+    private URL lookupResource() {
+        try {
+            return (URL) m_resources.get(0);
+        }
+        catch (IndexOutOfBoundsException e) {
+            return null;
+        }
+    }
+    
+    private Dictionary lookupResourceProperties() {
+    	try {
+    		return (Dictionary) m_resourceProperties.get(0);
+    	}
+        catch (IndexOutOfBoundsException e) {
+            return null;
+        }    	
+    }
+    
+    public Object getAutoConfigInstance() {
+        return lookupResource();
+    }
+
+    public String getAutoConfigName() {
+        return m_autoConfigInstance;
+    }
+
+    public Class getAutoConfigType() {
+        return URL.class;
+    }
+
+    public void invokeAdded(DependencyService service) {
+        // we remember these for future reference, needed for required callbacks
+        m_resourceInstance = lookupResource();
+        m_resourcePropertiesInstance = lookupResourceProperties();
+        invokeAdded(service, m_resourceInstance, m_resourcePropertiesInstance);
+    }
+
+    public void invokeRemoved(DependencyService service) {
+        invokeRemoved(service, m_resourceInstance, m_resourcePropertiesInstance);
+        m_resourceInstance = null;
+        m_resourcePropertiesInstance = null;
+    }
+
+    public ResourceDependency setPropagate(boolean propagate) {
+        ensureNotActive();
+        m_propagate = propagate;
+        return this;
+    }
+    
+    public ResourceDependency setPropagate(Object instance, String method) {
+        setPropagate(instance != null && method != null);
+        m_propagateCallbackInstance = instance;
+        m_propagateCallbackMethod = method;
+        return this;
+    }
+    
+    public Dictionary getProperties() {
+        URL resource = lookupResource();
+        Dictionary resourceProperties = lookupResourceProperties();
+        if (resource != null) {
+            if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
+                try {
+                    return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ URL.class }}, new Object[][] {{ resource }});
+                }
+                catch (InvocationTargetException e) {
+                    m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
+                }
+                catch (Exception e) {
+                    m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
+                }
+                throw new IllegalStateException("Could not invoke callback");
+            }
+            else {
+                Properties props = new Properties();
+                props.setProperty(ResourceHandler.HOST, resource.getHost());
+                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;
+            }
+        }
+        else {
+            throw new IllegalStateException("cannot find resource");
+        }
+    }
+
+    public boolean isPropagated() {
+        return m_propagate;
+    }
+
+    public ResourceDependency setInstanceBound(boolean isInstanceBound) {
+        setIsInstanceBound(isInstanceBound);
+        return this;
+    }
+
+    public String getName() {
+        StringBuilder sb = new StringBuilder();
+        if (m_resourceFilter != null) {
+            sb.append(m_resourceFilter);
+        }
+        if (m_trackedResource != null) {
+            sb.append(m_trackedResource.toString());
+        }
+        return sb.toString();
+    }
+
+    public String getType() {
+        return "resource";
+    }
+}



Mime
View raw message