You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2014/02/06 00:22:36 UTC
svn commit: r1564995 [2/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...
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java Wed Feb 5 23:22:32 2014
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import org.apache.felix.dm.impl.Logger;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Base bundle activator class. Subclass this activator if you want to use dependency
+ * management in your bundle. There are two methods you should implement:
+ * <code>init()</code> and <code>destroy()</code>. Both methods take two arguments,
+ * the bundle context and the dependency manager. The dependency manager can be used
+ * to define all the dependencies.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class DependencyActivatorBase implements BundleActivator {
+ private BundleContext m_context;
+ private DependencyManager m_manager;
+ private Logger m_logger;
+
+ /**
+ * Initialize the dependency manager. Here you can add all components and their dependencies.
+ * If something goes wrong and you do not want your bundle to be started, you can throw an
+ * exception. This exception will be passed on to the <code>start()</code> method of the
+ * bundle activator, causing the bundle not to start.
+ *
+ * @param context the bundle context
+ * @param manager the dependency manager
+ * @throws Exception if the initialization fails
+ */
+ public abstract void init(BundleContext context, DependencyManager manager) throws Exception;
+
+ /**
+ * Destroy the dependency manager. Here you can remove all components and their dependencies.
+ * Actually, the base class will clean up your dependencies anyway, so most of the time you
+ * don't need to do anything here.
+ * <p>
+ * If something goes wrong and you do not want your bundle to be stopped, you can throw an
+ * exception. This exception will be passed on to the <code>stop()</code> method of the
+ * bundle activator, causing the bundle not to stop.
+ *
+ * @param context the bundle context
+ * @param manager the dependency manager
+ * @throws Exception if the destruction fails
+ */
+ public void destroy(BundleContext context, DependencyManager manager) throws Exception { }
+
+ /**
+ * Start method of the bundle activator. Initializes the dependency manager
+ * and calls <code>init()</code>.
+ *
+ * @param context the bundle context
+ */
+ public void start(BundleContext context) throws Exception {
+ m_context = context;
+ m_logger = new Logger(context);
+ m_manager = new DependencyManager(context, m_logger);
+ init(m_context, m_manager);
+ }
+
+ /**
+ * Stop method of the bundle activator. Calls the <code>destroy()</code> method
+ * and cleans up all left over dependencies.
+ *
+ * @param context the bundle context
+ */
+ public void stop(BundleContext context) throws Exception {
+ destroy(m_context, m_manager);
+ m_manager.clear();
+ m_manager = null;
+ m_context = null;
+ }
+
+ /**
+ * Returns the bundle context that is associated with this bundle.
+ *
+ * @return the bundle context
+ */
+ public BundleContext getBundleContext() {
+ return m_context;
+ }
+
+ /**
+ * Returns the dependency manager that is associated with this bundle.
+ *
+ * @return the dependency manager
+ */
+ public DependencyManager getDependencyManager() {
+ return m_manager;
+ }
+
+ /**
+ * Returns the logger that is associated with this bundle. A logger instance
+ * is a proxy that will log to a real OSGi logservice if available and standard
+ * out if not.
+ *
+ * @return the logger
+ */
+ public Logger getLogger() {
+ return m_logger;
+ }
+
+ /**
+ * Creates a new component.
+ *
+ * @return the new component
+ */
+ public Component createComponent() {
+ return m_manager.createComponent();
+ }
+
+ /**
+ * Creates a new service dependency.
+ *
+ * @return the service dependency
+ */
+ public ServiceDependency createServiceDependency() {
+ return m_manager.createServiceDependency();
+ }
+
+ /**
+ * Creates a new temporal service dependency.
+ *
+ * @param timeout the max number of milliseconds to wait for a service availability.
+ * @return the service dependency
+ */
+ public TemporalServiceDependency createTemporalServiceDependency() {
+ return m_manager.createTemporalServiceDependency();
+ }
+
+ /**
+ * Creates a new configuration dependency.
+ *
+ * @return the configuration dependency
+ */
+ public ConfigurationDependency createConfigurationDependency() {
+ return m_manager.createConfigurationDependency();
+ }
+
+ /**
+ * Creates a new configuration property metadata.
+ *
+ * @return the configuration property metadata
+ */
+ public PropertyMetaData createPropertyMetaData() {
+ return m_manager.createPropertyMetaData();
+ }
+
+ /**
+ * Creates a new bundle dependency.
+ *
+ * @return the bundle dependency
+ */
+ public BundleDependency createBundleDependency() {
+ return m_manager.createBundleDependency();
+ }
+
+ /**
+ * Creates a new resource dependency.
+ *
+ * @return the resource dependency
+ */
+ public ResourceDependency createResourceDependency() {
+ return m_manager.createResourceDependency();
+ }
+
+ /**
+ * Creates a new aspect service.
+ *
+ * @return the aspect service
+ * @see DependencyManager#createAspectService(Class, String, int, String)
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String attributeName) {
+ return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, attributeName);
+ }
+
+ /**
+ * Creates a new aspect service.
+ *
+ * @return the aspect service
+ * @see DependencyManager#createAspectService(Class, String, int)
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking) {
+ return m_manager.createAspectService(serviceInterface, serviceFilter, ranking);
+ }
+
+ /**
+ * Creates a new aspect service.
+ *
+ * @return the aspect service
+ * @see DependencyManager#createAspectService(Class, String, int, String, String, String)
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove) {
+ return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, add, change, remove);
+ }
+
+ /**
+ * Creates a new adapter service.
+ *
+ * @return the adapter service
+ * @see DependencyManager#createAdapterService(Class, String)
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter) {
+ return m_manager.createAdapterService(serviceInterface, serviceFilter);
+ }
+
+ /**
+ * Creates a new adapter service.
+ *
+ * @return the adapter service
+ * @see DependencyManager#createAdapterService(Class, String, String)
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String autoConfig) {
+ return m_manager.createAdapterService(serviceInterface, serviceFilter, autoConfig);
+ }
+
+ /**
+ * Creates a new adapter service.
+ *
+ * @return the adapter service
+ * @see DependencyManager#createAdapterService(Class, String, String, String, String)
+ */
+ 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 adapter service.
+ * @return the adapter service
+ * @see DependencyManager#createAdapterService(Class, String, String, String, String, String)
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove, String swap) {
+ return m_manager.createAdapterService(serviceInterface, serviceFilter, add, change, remove, swap);
+ }
+
+ /**
+ * Creates a new resource adapter service.
+ *
+ * @return the resource adapter service
+ */
+ public Component createResourceAdapter(String resourceFilter, boolean propagate, Object callbackInstance, String callbackChanged) {
+ return m_manager.createResourceAdapterService(resourceFilter, propagate, callbackInstance, callbackChanged);
+ }
+
+ /**
+ * Creates a new resource adapter service.
+ *
+ * @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, 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);
+ }
+
+ /**
+ * Creates a new bundle adapter service.
+ *
+ * @return the bundle adapter service
+ */
+ public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
+ return m_manager.createBundleAdapterService(bundleStateMask, bundleFilter, propagate);
+ }
+
+ /**
+ * Creates a new factory configuration adapter service.
+ *
+ * @return the factory configuration adapter service
+ */
+ public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate) {
+ return m_manager.createFactoryConfigurationAdapterService(factoryPid, update, propagate);
+ }
+
+ /**
+ * Creates a new factory configuration adapter service.
+ *
+ * @return the factory configuration adapter service
+ */
+ public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, String heading, String desc, String localization, PropertyMetaData[] propertiesMetaData) {
+ return m_manager.createFactoryConfigurationAdapterService(factoryPid, update, propagate, heading, desc, localization, propertiesMetaData);
+ }
+}
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java Wed Feb 5 23:22:32 2014
@@ -0,0 +1,625 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.felix.dm.impl.AdapterServiceImpl;
+import org.apache.felix.dm.impl.AspectServiceImpl;
+import org.apache.felix.dm.impl.BundleAdapterServiceImpl;
+import org.apache.felix.dm.impl.ComponentImpl;
+import org.apache.felix.dm.impl.FactoryConfigurationAdapterServiceImpl;
+import org.apache.felix.dm.impl.Logger;
+import org.apache.felix.dm.impl.ResourceAdapterServiceImpl;
+import org.apache.felix.dm.impl.dependencies.BundleDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.ConfigurationDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.ResourceDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.ServiceDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.TemporalServiceDependencyImpl;
+import org.apache.felix.dm.impl.index.AspectFilterIndex;
+import org.apache.felix.dm.impl.index.AdapterFilterIndex;
+import org.apache.felix.dm.impl.index.ServiceRegistryCache;
+import org.apache.felix.dm.impl.index.multiproperty.MultiPropertyFilterIndex;
+import org.apache.felix.dm.impl.metatype.PropertyMetaDataImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * The dependency manager manages all components and their dependencies. Using
+ * this API you can declare all components and their dependencies. Under normal
+ * circumstances, you get passed an instance of this class through the
+ * <code>DependencyActivatorBase</code> subclass you use as your
+ * <code>BundleActivator</code>, but it is also possible to create your
+ * own instance.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DependencyManager {
+ public static final String ASPECT = "org.apache.felix.dependencymanager.aspect";
+ public static final String SERVICEREGISTRY_CACHE_INDICES = "org.apache.felix.dependencymanager.filterindex";
+ public static final String METHOD_CACHE_SIZE = "org.apache.felix.dependencymanager.methodcache";
+ private final BundleContext m_context;
+ private final Logger m_logger;
+ private List m_components = Collections.synchronizedList(new ArrayList());
+
+ /**
+ * Creates a new dependency manager. You need to supply the
+ * <code>BundleContext</code> to be used by the dependency
+ * manager to register services and communicate with the
+ * framework.
+ *
+ * @param context the bundle context
+ */
+ public DependencyManager(BundleContext context) {
+ this(context, new Logger(context));
+ }
+
+ DependencyManager(BundleContext context, Logger logger) {
+ m_context = createContext(context);
+ m_logger = logger;
+ synchronized (m_dependencyManagers) {
+ m_dependencyManagers.add(new WeakReference(this));
+ }
+ }
+
+ // service registry cache
+ private static ServiceRegistryCache m_serviceRegistryCache;
+ private static final Set /* WeakReference<DependencyManager> */ m_dependencyManagers = new HashSet();
+ static {
+ String index = System.getProperty(SERVICEREGISTRY_CACHE_INDICES);
+ if (index != null) {
+ Bundle bundle = FrameworkUtil.getBundle(DependencyManager.class);
+ try {
+ if (bundle.getState() != Bundle.ACTIVE) {
+ bundle.start();
+ }
+ BundleContext bundleContext = bundle.getBundleContext();
+
+ m_serviceRegistryCache = new ServiceRegistryCache(bundleContext);
+ m_serviceRegistryCache.open(); // TODO close it somewhere
+ String[] props = index.split(";");
+ for (int i = 0; i < props.length; i++) {
+ if (props[i].equals("*aspect*")) {
+ m_serviceRegistryCache.addFilterIndex(new AspectFilterIndex());
+ }
+ else if (props[i].equals("*adapter*")) {
+ m_serviceRegistryCache.addFilterIndex(new AdapterFilterIndex());
+ }
+ else {
+ m_serviceRegistryCache.addFilterIndex(new MultiPropertyFilterIndex(props[i]));
+ }
+ }
+ }
+ catch (BundleException e) {
+ // if we cannot start ourselves, we cannot use the indices
+ // TODO we might want to warn people about this
+ }
+ }
+ }
+
+ public static List getDependencyManagers() {
+ List /* DependencyManager */ result = new ArrayList();
+ synchronized (m_dependencyManagers) {
+ Iterator iterator = m_dependencyManagers.iterator();
+ while (iterator.hasNext()) {
+ WeakReference reference = (WeakReference) iterator.next();
+ DependencyManager manager = (DependencyManager) reference.get();
+ if (manager != null) {
+ try {
+ manager.getBundleContext().getBundle();
+ result.add(manager);
+ continue;
+ }
+ catch (IllegalStateException e) {
+ }
+ }
+ iterator.remove();
+ }
+ }
+ return result;
+ }
+
+ private BundleContext createContext(BundleContext context) {
+ if (m_serviceRegistryCache != null) {
+ return m_serviceRegistryCache.createBundleContextInterceptor(context);
+ }
+ else {
+ return context;
+ }
+ }
+
+ public BundleContext getBundleContext() {
+ return m_context;
+ }
+
+ /**
+ * Adds a new service to the dependency manager. After the service was added
+ * it will be started immediately.
+ *
+ * @param service the service to add
+ */
+ public void add(Component service) {
+ m_components.add(service);
+ service.start();
+ }
+
+ /**
+ * Removes a service from the dependency manager. Before the service is removed
+ * it is stopped first.
+ *
+ * @param service the service to remove
+ */
+ public void remove(Component service) {
+ service.stop();
+ m_components.remove(service);
+ }
+
+ /**
+ * Creates a new service.
+ *
+ * @return the new service
+ */
+ public Component createComponent() {
+ return new ComponentImpl(m_context, this, m_logger);
+ }
+
+ /**
+ * Creates a new service dependency.
+ *
+ * @return the service dependency
+ */
+ public ServiceDependency createServiceDependency() {
+ return new ServiceDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new temporal service dependency.
+ *
+ * @return a new temporal service dependency
+ */
+ public TemporalServiceDependency createTemporalServiceDependency() {
+ return new TemporalServiceDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new configuration dependency.
+ *
+ * @return the configuration dependency
+ */
+ public ConfigurationDependency createConfigurationDependency() {
+ return new ConfigurationDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new configuration property metadata.
+ *
+ * @return the configuration property metadata.
+ */
+ public PropertyMetaData createPropertyMetaData() {
+ return new PropertyMetaDataImpl();
+ }
+
+ /**
+ * Creates a new bundle dependency.
+ *
+ * @return a new BundleDependency instance.
+ */
+ public BundleDependency createBundleDependency() {
+ return new BundleDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new resource dependency.
+ *
+ * @return the resource dependency
+ */
+ public ResourceDependency createResourceDependency() {
+ return new ResourceDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new aspect. The aspect will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an aspect will be created based on the aspect implementation class.
+ * The aspect will be registered with the same interface and properties
+ * as the original service, plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_service")
+ * .setImplementation(ExistingServiceAspect.class)
+ * );
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the aspect to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param ranking the level used to organize the aspect chain ordering
+ * @param autoConfig the aspect implementation field name where to inject original service.
+ * If null, any field matching the original service will be injected.
+ * @return a service that acts as a factory for generating aspects
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String autoConfig) {
+ return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null, null);
+ }
+ /**
+ * Creates a new aspect. The aspect will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an aspect will be created based on the aspect implementation class.
+ * The aspect will be registered with the same interface and properties
+ * as the original service, plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAspectService(ExistingService.class, "(foo=bar)", 10)
+ * .setImplementation(ExistingServiceAspect.class)
+ * );
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the aspect to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param ranking the level used to organize the aspect chain ordering
+ * @return a service that acts as a factory for generating aspects
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking) {
+ return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null, null);
+ }
+ /**
+ * Creates a new aspect. The aspect will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an aspect will be created based on the aspect implementation class.
+ * The aspect will be registered with the same interface and properties
+ * as the original service, plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
+ * .setImplementation(ExistingServiceAspect.class)
+ * );
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the aspect to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param ranking the level used to organize the aspect chain ordering
+ * @param add name of the callback method to invoke on add
+ * @param change name of the callback method to invoke on change
+ * @param remove name of the callback method to invoke on remove
+ * @return a service that acts as a factory for generating aspects
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove) {
+ return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, null);
+ }
+
+ /**
+ * Creates a new aspect. The aspect will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an aspect will be created based on the aspect implementation class.
+ * The aspect will be registered with the same interface and properties
+ * as the original service, plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
+ * .setImplementation(ExistingServiceAspect.class)
+ * );
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the aspect to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param ranking the level used to organize the aspect chain ordering
+ * @param add name of the callback method to invoke on add
+ * @param change name of the callback method to invoke on change
+ * @param remove name of the callback method to invoke on remove
+ * @param swap name of the callback method to invoke on swap
+ * @return a service that acts as a factory for generating aspects
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove, String swap) {
+ return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, swap);
+ }
+
+ /**
+ * Creates a new adapter. The adapter will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface and existing properties
+ * from the original service plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
+ * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+ * .setImplementation(AdapterImpl.class);
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the adapter to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @return a service that acts as a factory for generating adapters
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null);
+ }
+ /**
+ * Creates a new adapter. The adapter will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface and existing properties
+ * from the original service plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "m_service")
+ * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+ * .setImplementation(AdapterImpl.class);
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the adapter to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param autoConfig the name of the member to inject the service into
+ * @return a service that acts as a factory for generating adapters
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String autoConfig) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null);
+ }
+ /**
+ * Creates a new adapter. The adapter will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface and existing properties
+ * from the original service plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
+ * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+ * .setImplementation(AdapterImpl.class);
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the adapter to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param add name of the callback method to invoke on add
+ * @param change name of the callback method to invoke on change
+ * @param remove name of the callback method to invoke on remove
+ * @param swap name of the callback method to invoke on swap
+ * @return a service that acts as a factory for generating adapters
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove, String swap) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove, swap);
+ }
+
+ /** @see DependencyManager#createAdapterService(Class, String, String, String, String, String) */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove);
+ }
+
+ /**
+ * Creates a new resource adapter. The adapter will be applied to any resource that
+ * matches the specified filter condition. For each matching resource
+ * an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface and existing properties
+ * from the original resource plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createResourceAdapterService("(&(path=/test)(repository=TestRepository))", true)
+ * // The interface to use when registering adapter
+ * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+ * // the implementation of the adapter
+ * .setImplementation(AdapterServiceImpl.class);
+ * </pre></blockquote>
+ *
+ * @param resourceFilter the filter condition to use with the resource
+ * @param resourcePropertiesFilter the filter condition on the resource properties to use with the resource
+ * @param propagate <code>true</code> if properties from the resource should be propagated to the service
+ * @param callbackInstance instance to invoke the callback on
+ * @param callbackChanged the name of the callback method
+ * @return a service that acts as a factory for generating resource adapters
+ * @see Resource
+ */
+ public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackChanged) {
+ return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, null, callbackChanged);
+ }
+
+ /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
+ public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackSet, String callbackChanged) {
+ return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, callbackSet, callbackChanged);
+ }
+
+ /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
+ public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
+ return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, null, callbackChanged);
+ }
+
+ /** @see DependencyManager#createResourceAdapterService(String, boolean, Object, String) */
+ public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged) {
+ return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, callbackSet, callbackChanged);
+ }
+
+ /**
+ * Creates a new bundle adapter. The adapter will be applied to any bundle that
+ * matches the specified bundle state mask and filter condition. For each matching
+ * bundle an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface
+ *
+ * TODO and existing properties from the original resource plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createBundleAdapterService(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE,
+ * "(Bundle-SymbolicName=org.apache.felix.dependencymanager)",
+ * true)
+ * // The interface to use when registering adapter
+ * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+ * // the implementation of the adapter
+ * .setImplementation(AdapterServiceImpl.class);
+ * </pre></blockquote>
+ *
+ * @param bundleStateMask the bundle state mask to apply
+ * @param bundleFilter the filter to apply to the bundle manifest
+ * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
+ * @return a service that acts as a factory for generating bundle adapters
+ */
+ public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
+ return new BundleAdapterServiceImpl(this, bundleStateMask, bundleFilter, propagate);
+ }
+
+ /**
+ * Creates a new Managed Service Factory Configuration Adapter. For each new Config Admin factory configuration matching
+ * the factoryPid, an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface, and with the specified adapter service properties.
+ * Depending on the <code>propagate</code> parameter, every public factory configuration properties
+ * (which don't start with ".") will be propagated along with the adapter service properties.
+ * It will also inherit all dependencies.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createFactoryConfigurationAdapterService("MyFactoryPid", "update", true)
+ * // The interface to use when registering adapter
+ * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+ * // the implementation of the adapter
+ * .setImplementation(AdapterServiceImpl.class);
+ * </pre></blockquote>
+ *
+ * @param factoryPid the pid matching the factory configuration
+ * @param update the adapter method name that will be notified when the factory configuration is created/updated.
+ * @param propagate true if public factory configuration should be propagated to the adapter service properties
+ * @return a service that acts as a factory for generating the managed service factory configuration adapter
+ */
+ public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate) {
+ return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate);
+ }
+
+ /**
+ * Creates a new Managed Service Factory Configuration Adapter with meta type support. For each new Config Admin
+ * factory configuration matching the factoryPid, an adapter will be created based on the adapter implementation
+ * class. The adapter will be registered with the specified interface, and with the specified adapter service
+ * properties. Depending on the <code>propagate</code> parameter, every public factory configuration properties
+ * (which don't start with ".") will be propagated along with the adapter service properties.
+ * It will also inherit all dependencies.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * PropertyMetaData[] propertiesMetaData = new PropertyMetaData[] {
+ * manager.createPropertyMetaData()
+ * .setCardinality(Integer.MAX_VALUE)
+ * .setType(String.class)
+ * .setHeading("English words")
+ * .setDescription("Declare here some valid english words")
+ * .setDefaults(new String[] {"hello", "world"})
+ * .setId("words")
+ * };
+ *
+ * manager.add(createFactoryConfigurationAdapterService("FactoryPid",
+ * "updated",
+ * true, // propagate CM settings
+ * "EnglishDictionary",
+ * "English dictionary configuration properties",
+ * null,
+ * propertiesMetaData)
+ * .setImplementation(Adapter.class));
+ * </pre></blockquote>
+ *
+ * @param factoryPid the pid matching the factory configuration
+ * @param update the adapter method name that will be notified when the factory configuration is created/updated.
+ * @param propagate true if public factory configuration should be propagated to the adapter service properties
+ * @param heading The label used to display the tab name (or section) where the properties are displayed.
+ * Example: "Printer Service"
+ * @param desc A human readable description of the factory PID this configuration is associated with.
+ * Example: "Configuration for the PrinterService bundle"
+ * @param localization Points to the basename of the Properties file that can localize the Meta Type informations.
+ * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
+ * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization
+ * on page 68). You can specify a specific localization basename file using this parameter
+ * (e.g. <code>"person"</code> will match person_du_NL.properties in the root bundle directory).
+ * @param propertiesMetaData Array of MetaData regarding configuration properties
+ * @return a service that acts as a factory for generating the managed service factory configuration adapter
+ */
+ public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate, String heading, String desc, String localization, PropertyMetaData[] propertiesMetaData) {
+ return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate, m_context, m_logger, heading, desc, localization, propertiesMetaData);
+ }
+
+ /**
+ * Returns a list of services.
+ *
+ * @return a list of services
+ */
+ public List getComponents() {
+ synchronized (m_components) {
+ List copyComponents = new ArrayList(m_components.size());
+ for (int i = 0; i < m_components.size(); i++) {
+ copyComponents.add(m_components.get(i));
+ }
+ return copyComponents;
+ }
+ }
+
+ /**
+ * Removes all components and their dependencies.
+ */
+ public void clear() {
+ Component[] components;
+ synchronized (m_components) {
+ components = (Component[]) m_components.toArray(new Component[m_components.size()]);
+ }
+ for (int i = components.length - 1; i >= 0; i--) {
+ Component component = (Component) components[i];
+ remove(component);
+ // remove any state listeners that are still registered
+ if (component instanceof ComponentImpl) {
+ ComponentImpl si = (ComponentImpl) component;
+ si.removeStateListeners();
+ }
+ }
+ }
+}
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java Wed Feb 5 23:22:32 2014
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * Interface to the component, so dependencies can interact with it.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface DependencyService {
+ /**
+ * Will be called when the dependency becomes available.
+ *
+ * @param dependency the dependency
+ */
+ public void dependencyAvailable(Dependency dependency);
+
+ /**
+ * Will be called when the dependency becomes unavailable .
+ *
+ * @param dependency the dependency
+ */
+ public void dependencyUnavailable(Dependency dependency);
+
+ /**
+ * Will be called when the dependency changes.
+ *
+ * @param dependency the dependency
+ */
+ public void dependencyChanged(Dependency dependency);
+
+ /**
+ * Returns the component instance.
+ *
+ * @return component instance
+ */
+ public Object getService(); // is also defined on the Service interface
+
+ /**
+ * Initializes the component. Instantiates it and injects the default injectables such
+ * as {@link BundleContext} and {@link DependencyManager}.
+ */
+ public void initService(); // was an implementation method TODO we use it in ConfDepImpl but should not (probably)
+
+ /**
+ * Returns <code>true</code> if this component is registered. In other words, all
+ * its required dependencies are available.
+ *
+ * @return <code>true</code> if the component is registered
+ */
+ public boolean isRegistered(); // impl method
+
+ /**
+ * Returns a list of all instances that are part of the composition for this component.
+ *
+ * @return an array of instances
+ */
+ public Object[] getCompositionInstances(); // impl method
+
+ /**
+ * Returns <code>true</code> if this component is instantiated.
+ *
+ * @return <code>true</code> if this component is instantiated
+ */
+ public boolean isInstantiated();
+
+ /**
+ * Can be called by the dependency whenever it wants to invoke callback methods.
+ */
+ public void invokeCallbackMethod(Object[] instances, String methodName, Class[][] signatures, Object[][] parameters);
+
+ /**
+ * Returns the component interface.
+ *
+ * @return the component interface
+ */
+ public Component getServiceInterface();
+
+ /**
+ * Injects the dependency into autoconfig class field (if any) of the dependency service.
+ * @param dependency
+ */
+ public void autoConfig(final Dependency dependency);
+
+ /**
+ * Propagates the dependency properties to the ones provided by the dependency service.
+ * No effet if the dependency is not configured with the setPropagate method.
+ *
+ * @param dependency the dependency whose properties will be propagated to the service properties of this dependency service.
+ *
+ * @see ServiceDependency#setPropagate(boolean)
+ * @see ServiceDependency#setPropagate(String)
+ */
+ public void propagate(final Dependency dependency);
+}
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java Wed Feb 5 23:22:32 2014
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.util.List;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+
+/**
+ * A filter index is an interface you can implement to create your own, optimized index for specific filter expressions.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface FilterIndex {
+ /** Opens this filter index. */
+ public void open(BundleContext context);
+ /** Closes this filter index. */
+ public void close();
+ /** Determines if the combination of class and filter is applicable for this filter index. */
+ public boolean isApplicable(String clazz, String filter);
+ /** Returns all service references that match the specified class and filter. */
+ public List /* <ServiceReference> */ getAllServiceReferences(String clazz, String filter);
+ /** Invoked whenever a service event occurs. */
+ public void serviceChanged(ServiceEvent event);
+ /** Adds a service listener to this filter index. */
+ public void addServiceListener(ServiceListener listener, String filter);
+ /** Removes a service listener from this filter index. If the listener is not present in the filter index, this method does nothing. */
+ public void removeServiceListener(ServiceListener listener);
+}
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java Wed Feb 5 23:22:32 2014
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Utility methods for invoking callbacks. Lookups of callbacks are accellerated by using a LRU cache.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class InvocationUtil {
+ private static final Map /* <Key, Method> */ m_methodCache;
+ static {
+ int size = 2048;
+ try {
+ String value = System.getProperty(DependencyManager.METHOD_CACHE_SIZE);
+ if (value != null) {
+ size = Integer.parseInt(value);
+ }
+ }
+ catch (Exception e) {}
+ m_methodCache = new LRUMap(Math.max(size, 64));
+ }
+
+ /**
+ * Invokes a callback method on an instance. The code will search for a callback method with
+ * the supplied name and any of the supplied signatures in order, invoking the first one it finds.
+ *
+ * @param instance the instance to invoke the method on
+ * @param methodName the name of the method
+ * @param signatures the ordered list of signatures to look for
+ * @param parameters the parameter values to use for each potential signature
+ * @return whatever the method returns
+ * @throws NoSuchMethodException when no method could be found
+ * @throws IllegalArgumentException when illegal values for this methods arguments are supplied
+ * @throws IllegalAccessException when the method cannot be accessed
+ * @throws InvocationTargetException when the method that was invoked throws an exception
+ */
+ public static Object invokeCallbackMethod(Object instance, String methodName, Class[][] signatures, Object[][] parameters) throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+ Class currentClazz = instance.getClass();
+ while (currentClazz != null && currentClazz != Object.class) {
+ try {
+ return invokeMethod(instance, currentClazz, methodName, signatures, parameters, false);
+ }
+ catch (NoSuchMethodException nsme) {
+ // ignore
+ }
+ currentClazz = currentClazz.getSuperclass();
+ }
+ throw new NoSuchMethodException(methodName);
+ }
+
+ /**
+ * Invoke a method on an instance.
+ *
+ * @param object the instance to invoke the method on
+ * @param clazz the class of the instance
+ * @param name the name of the method
+ * @param signatures the signatures to look for in order
+ * @param parameters the parameter values for the signatures
+ * @param isSuper <code>true</code> if this is a superclass and we should therefore not look for private methods
+ * @return whatever the method returns
+ * @throws NoSuchMethodException when no method could be found
+ * @throws IllegalArgumentException when illegal values for this methods arguments are supplied
+ * @throws IllegalAccessException when the method cannot be accessed
+ * @throws InvocationTargetException when the method that was invoked throws an exception
+ */
+ public static Object invokeMethod(Object object, Class clazz, String name, Class[][] signatures, Object[][] parameters, boolean isSuper) throws NoSuchMethodException, InvocationTargetException, IllegalArgumentException, IllegalAccessException {
+ if (object == null) {
+ throw new IllegalArgumentException("Instance cannot be null");
+ }
+ if (clazz == null) {
+ throw new IllegalArgumentException("Class cannot be null");
+ }
+
+ // if we're talking to a proxy here, dig one level deeper to expose the
+ // underlying invocation handler (we do the same for injecting instances)
+ if (Proxy.isProxyClass(clazz)) {
+ object = Proxy.getInvocationHandler(object);
+ clazz = object.getClass();
+ }
+
+ Method m = null;
+ for (int i = 0; i < signatures.length; i++) {
+ Class[] signature = signatures[i];
+ m = getDeclaredMethod(clazz, name, signature, isSuper);
+ if (m != null) {
+ return m.invoke(object, parameters[i]);
+ }
+ }
+ throw new NoSuchMethodException(name);
+ }
+
+ private static Method getDeclaredMethod(Class clazz, String name, Class[] signature, boolean isSuper) {
+ // first check our cache
+ Key key = new Key(clazz, name, signature);
+ Method m = null;
+ synchronized (m_methodCache) {
+ m = (Method) m_methodCache.get(key);
+ if (m != null) {
+ return m;
+ }
+ else if (m_methodCache.containsKey(key)) {
+ // the key is in our cache, it just happens to have a null value
+ return null;
+ }
+ }
+ // then do a lookup
+ try {
+ m = clazz.getDeclaredMethod(name, signature);
+ if (!(isSuper && Modifier.isPrivate(m.getModifiers()))) {
+ m.setAccessible(true);
+ }
+ }
+ catch (NoSuchMethodException e) {
+ // ignore
+ }
+ synchronized (m_methodCache) {
+ m_methodCache.put(key, m);
+ }
+ return m;
+ }
+
+ public static class Key {
+ private final Class m_clazz;
+ private final String m_name;
+ private final Class[] m_signature;
+
+ public Key(Class clazz, String name, Class[] signature) {
+ m_clazz = clazz;
+ m_name = name;
+ m_signature = signature;
+ }
+
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((m_clazz == null) ? 0 : m_clazz.hashCode());
+ result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
+ result = prime * result + Arrays.hashCode(m_signature);
+ return result;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Key other = (Key) obj;
+ if (m_clazz == null) {
+ if (other.m_clazz != null)
+ return false;
+ }
+ else if (!m_clazz.equals(other.m_clazz))
+ return false;
+ if (m_name == null) {
+ if (other.m_name != null)
+ return false;
+ }
+ else if (!m_name.equals(other.m_name))
+ return false;
+ if (!Arrays.equals(m_signature, other.m_signature))
+ return false;
+ return true;
+ }
+ }
+
+ public static class LRUMap extends LinkedHashMap {
+ private final int m_size;
+
+ public LRUMap(int size) {
+ m_size = size;
+ }
+
+ protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
+ return size() > m_size;
+ }
+ }
+}
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java Wed Feb 5 23:22:32 2014
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless
+ * required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+/**
+ * This interface defines meta data regarding a given configuration property.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface PropertyMetaData {
+ /**
+ * The label used to display the property. Example: "Log Level".
+ *
+ * @return The label used to display the property (may be localized)
+ */
+ public PropertyMetaData setHeading(String heading);
+
+ /**
+ * The key of a ConfigurationAdmin property. Example: "printer.logLevel"
+ *
+ * @return The Configuration Admin property name
+ */
+ public PropertyMetaData setId(String id);
+
+ /**
+ * Returns the property primitive type. If must be either one of the following types:<p>
+ * <ul>
+ * <li>String.class</li>
+ * <li>Long.class</li>
+ * <li>Integer.class</li>
+ * <li>Character.class</li>
+ * <li>Byte.class</li>
+ * <li>Double.class</li>
+ * <li>Float.class</li>
+ * <li>Boolean.class</li>
+ * </ul>
+ */
+ public PropertyMetaData setType(Class type);
+
+ /**
+ * Returns a default for this property. The object must be of the appropriate type as defined by the cardinality and getType().
+ * The return type is a list of String objects that can be converted to the appropriate type. The cardinality of the return
+ * array must follow the absolute cardinality of this type. E.g. if the cardinality = 0, the array must contain 1 element.
+ * If the cardinality is 1, it must contain 0 or 1 elements. If it is -5, it must contain from 0 to max 5 elements. Note that
+ * the special case of a 0 cardinality, meaning a single value, does not allow arrays or vectors of 0 elements.
+ */
+ public PropertyMetaData setDefaults(String[] defaults);
+
+ /**
+ * Returns the property description. The description may be localized and must describe the semantics of this type and any
+ * constraints. Example: "Select the log level for the Printer Service".
+ *
+ * @return a localizable description of the property.
+ */
+ public PropertyMetaData setDescription(String description);
+
+ /**
+ * Return the cardinality of this property. The OSGi environment handles multi valued properties in arrays ([]) or in Vector objects.
+ * The return value is defined as follows:<p>
+ *
+ * <ul>
+ * <li> x = Integer.MIN_VALUE no limit, but use Vector</li>
+ * <li> x < 0 -x = max occurrences, store in Vector</li>
+ * <li> x > 0 x = max occurrences, store in array []</li>
+ * <li> x = Integer.MAX_VALUE no limit, but use array []</li>
+ * <li> x = 0 1 occurrence required</li>
+ * </ul>
+ */
+ public PropertyMetaData setCardinality(int cardinality);
+
+ /**
+ * Tells if this property is required or not.
+ */
+ public PropertyMetaData setRequired(boolean required);
+
+ /**
+ * Return a list of valid options for this property (the labels may be localized).
+ *
+ * @return the list of valid options for this property.
+ */
+ public PropertyMetaData addOption(String optionLabel, String optionValue);
+}
\ No newline at end of file
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java Wed Feb 5 23:22:32 2014
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.net.URL;
+
+/**
+ * A resource dependency is a dependency on a resource. A resource in this context is an object that is
+ * identified by a URL. Resources should somehow be provided by an external component, the resource
+ * provider. These dependencies then react on them becoming available or not. Use cases for such dependencies
+ * are resources that are embedded in bundles, in a workspace or some remote or local repository, etc.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ResourceDependency extends Dependency, ComponentDependencyDeclaration, ResourceHandler {
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added or removed. When you specify callbacks, the auto configuration
+ * feature is automatically turned off, because we're assuming you don't need it in this
+ * case.
+ *
+ * @param added the method to call when a service was added
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ResourceDependency setCallbacks(String added, String removed);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added, changed or removed. When you specify callbacks, the auto
+ * configuration feature is automatically turned off, because we're assuming you don't
+ * need it in this case.
+ *
+ * @param added the method to call when a service was added
+ * @param changed the method to call when a service was changed
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ResourceDependency setCallbacks(String added, String changed, String removed);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added or removed. They are called on the instance you provide. When you
+ * specify callbacks, the auto configuration feature is automatically turned off, because
+ * we're assuming you don't need it in this case.
+ *
+ * @param instance the instance to call the callbacks on
+ * @param added the method to call when a service was added
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ResourceDependency setCallbacks(Object instance, String added, String removed);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added, changed or removed. They are called on the instance you provide. When you
+ * specify callbacks, the auto configuration feature is automatically turned off, because
+ * we're assuming you don't need it in this case.
+ *
+ * @param instance the instance to call the callbacks on
+ * @param added the method to call when a service was added
+ * @param changed the method to call when a service was changed
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ResourceDependency setCallbacks(Object instance, String added, String changed, String removed);
+
+ /**
+ * Sets auto configuration for this service. Auto configuration allows the
+ * dependency to fill in any attributes in the service implementation that
+ * are of the same type as this dependency. Default is on.
+ *
+ * @param autoConfig the value of auto config
+ * @return this service dependency
+ */
+ public ResourceDependency setAutoConfig(boolean autoConfig);
+
+ /**
+ * Sets auto configuration for this service. Auto configuration allows the
+ * dependency to fill in the attribute in the service implementation that
+ * has the same type and instance name.
+ *
+ * @param instanceName the name of attribute to auto config
+ * @return this service dependency
+ */
+ public ResourceDependency setAutoConfig(String instanceName);
+
+ /**
+ * Sets the resource for this dependency.
+ *
+ * @param resource the URL of the resource
+ */
+ public ResourceDependency setResource(URL resource);
+
+ /**
+ * Determines if this is a required dependency or not.
+ *
+ * @param required <code>true</code> if the dependency is required
+ */
+ public ResourceDependency setRequired(boolean required);
+
+ /**
+ * Sets the filter condition for this resource dependency.
+ *
+ * @param resourceFilter the filter condition
+ */
+ public ResourceDependency setFilter(String resourceFilter);
+
+ /** @see ResourceDependency#setPropagate(Object, String) */
+ public ResourceDependency setPropagate(boolean propagate);
+
+ /**
+ * Sets an Object instance and a callback method used to propagate some properties to the provided service properties.
+ * The method will be invoked on the specified object instance and must have one of the following signatures:<p>
+ * <ul><li>Dictionary callback(ServiceReference, Object service)
+ * <li>Dictionary callback(ServiceReference)
+ * </ul>
+ * @param instance the Object instance which is used to retrieve propagated service properties
+ * @param method the method to invoke for retrieving the properties to be propagated to the service properties.
+ * @return this service dependency.
+ */
+ public ResourceDependency setPropagate(Object instance, String method);
+
+ /**
+ * Sets this dependency to be instance bound or not.
+ *
+ * @param isInstanceBound <code>true</code> if this dependency should be instance bound
+ */
+ public ResourceDependency setInstanceBound(boolean isInstanceBound);
+}
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java Wed Feb 5 23:22:32 2014
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.net.URL;
+import java.util.Dictionary;
+
+/**
+ * Service interface for anybody wanting to be notified of changes to resources.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ResourceHandler {
+ /** Name of the property that's used to describe the filter condition for a resource. */
+ public static final String FILTER = "filter";
+ /** Exact URL that this handler is looking for. Can be used instead of a filter to be very explicit about the resource you're looking for. */
+ public static final String URL = "url";
+ /** The host part of the URL. */
+ public static final String HOST = "host";
+ /** The path part of the URL. */
+ public static final String PATH = "path";
+ /** The protocol part of the URL. */
+ public static final String PROTOCOL = "protocol";
+ /** The port part of the URL. */
+ public static final String PORT = "port";
+
+ /**
+ * @deprecated Please use {@link #added(URL, Dictionary)} instead. When both are specified,
+ * the new method takes precedence and the deprecated one is not invoked.
+ */
+ public void added(URL resource);
+
+ /**
+ * Invoked whenever a new resource is added.
+ */
+ public void added(URL resource, Dictionary resourceProperties);
+
+ /**
+ * @deprecated Please use {@link #changed(URL, Dictionary)} instead. When both are specified,
+ * the new method takes precedence and the deprecated one is not invoked.
+ */
+ public void changed(URL resource);
+
+ /**
+ * Invoked whenever an existing resource changes.
+ */
+ public void changed(URL resource, Dictionary resourceProperties);
+
+ /**
+ * @deprecated Please use {@link #removed(URL, Dictionary)} instead. When both are specified,
+ * the new method takes precedence and the deprecated one is not invoked.
+ */
+ public void removed(URL resource);
+
+ /**
+ * Invoked whenever an existing resource is removed.
+ */
+ public void removed(URL resource, Dictionary resourceProperties);
+}
Added: felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java?rev=1564995&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java (added)
+++ felix/sandbox/pderop/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java Wed Feb 5 23:22:32 2014
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Properties;
+
+/**
+ * Utility class for resource handling.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ResourceUtil {
+ /**
+ * Creates a set of properties for a resource based on its URL.
+ *
+ * @param url the URL
+ * @return a set of properties
+ */
+ public static Dictionary createProperties(URL url) {
+ Properties props = new Properties();
+ props.setProperty(ResourceHandler.PROTOCOL, url.getProtocol());
+ props.setProperty(ResourceHandler.HOST, url.getHost());
+ props.setProperty(ResourceHandler.PORT, Integer.toString(url.getPort()));
+ props.setProperty(ResourceHandler.PATH, url.getPath());
+ return props;
+ }
+}