You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ui...@apache.org on 2012/02/24 11:47:51 UTC
svn commit: r1293173 [2/8] - in
/felix/sandbox/uiterlix/dependencymanager/core: ./ .externalToolBuilders/
.settings/ src/ src/main/ src/main/java/ src/main/java/org/
src/main/java/org/apache/ src/main/java/org/apache/felix/
src/main/java/org/apache/fel...
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,585 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.felix.dm.impl.AdapterServiceImpl;
+import org.apache.felix.dm.impl.AspectServiceImpl;
+import org.apache.felix.dm.impl.BundleAdapterServiceImpl;
+import org.apache.felix.dm.impl.ComponentImpl;
+import org.apache.felix.dm.impl.FactoryConfigurationAdapterServiceImpl;
+import org.apache.felix.dm.impl.Logger;
+import org.apache.felix.dm.impl.ResourceAdapterServiceImpl;
+import org.apache.felix.dm.impl.dependencies.BundleDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.ConfigurationDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.ResourceDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.ServiceDependencyImpl;
+import org.apache.felix.dm.impl.dependencies.TemporalServiceDependencyImpl;
+import org.apache.felix.dm.impl.index.AspectFilterIndex;
+import org.apache.felix.dm.impl.index.MultiPropertyExactFilter;
+import org.apache.felix.dm.impl.index.ServiceRegistryCache;
+import org.apache.felix.dm.impl.metatype.PropertyMetaDataImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * The dependency manager manages all components and their dependencies. Using
+ * this API you can declare all components and their dependencies. Under normal
+ * circumstances, you get passed an instance of this class through the
+ * <code>DependencyActivatorBase</code> subclass you use as your
+ * <code>BundleActivator</code>, but it is also possible to create your
+ * own instance.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DependencyManager {
+ public static final String ASPECT = "org.apache.felix.dependencymanager.aspect";
+ public static final String SERVICEREGISTRY_CACHE_INDICES = "org.apache.felix.dependencymanager.filterindex";
+ public static final String METHOD_CACHE_SIZE = "org.apache.felix.dependencymanager.methodcache";
+ private final BundleContext m_context;
+ private final Logger m_logger;
+ private List m_components = Collections.synchronizedList(new ArrayList());
+
+ /**
+ * Creates a new dependency manager. You need to supply the
+ * <code>BundleContext</code> to be used by the dependency
+ * manager to register services and communicate with the
+ * framework.
+ *
+ * @param context the bundle context
+ */
+ public DependencyManager(BundleContext context) {
+ this(context, new Logger(context));
+ }
+
+ DependencyManager(BundleContext context, Logger logger) {
+ m_context = createContext(context);
+ m_logger = logger;
+ synchronized (m_dependencyManagers) {
+ m_dependencyManagers.add(new WeakReference(this));
+ }
+ }
+
+ // service registry cache
+ private static ServiceRegistryCache m_serviceRegistryCache;
+ private static final Set /* WeakReference<DependencyManager> */ m_dependencyManagers = new HashSet();
+ static {
+ String index = System.getProperty(SERVICEREGISTRY_CACHE_INDICES);
+ if (index != null) {
+ Bundle bundle = FrameworkUtil.getBundle(DependencyManager.class);
+ try {
+ if (bundle.getState() != Bundle.ACTIVE) {
+ bundle.start();
+ }
+ BundleContext bundleContext = bundle.getBundleContext();
+
+ m_serviceRegistryCache = new ServiceRegistryCache(bundleContext);
+ m_serviceRegistryCache.open(); // TODO close it somewhere
+ String[] props = index.split(";");
+ for (int i = 0; i < props.length; i++) {
+ if (props[i].equals("*aspect*")) {
+ m_serviceRegistryCache.addFilterIndex(new AspectFilterIndex());
+ }
+ else {
+ String[] propList = props[i].split(",");
+ m_serviceRegistryCache.addFilterIndex(new MultiPropertyExactFilter(propList));
+ }
+ }
+ }
+ catch (BundleException e) {
+ // if we cannot start ourselves, we cannot use the indices
+ // TODO we might want to warn people about this
+ }
+ }
+ }
+
+ public static List getDependencyManagers() {
+ List /* DependencyManager */ result = new ArrayList();
+ synchronized (m_dependencyManagers) {
+ Iterator iterator = m_dependencyManagers.iterator();
+ while (iterator.hasNext()) {
+ WeakReference reference = (WeakReference) iterator.next();
+ DependencyManager manager = (DependencyManager) reference.get();
+ if (manager != null) {
+ try {
+ manager.getBundleContext().getBundle();
+ result.add(manager);
+ continue;
+ }
+ catch (IllegalStateException e) {
+ }
+ }
+ iterator.remove();
+ }
+ }
+ return result;
+ }
+
+ private BundleContext createContext(BundleContext context) {
+ if (m_serviceRegistryCache != null) {
+// System.out.println("DM: Enabling bundle context interceptor for bundle #" + context.getBundle().getBundleId());
+ return m_serviceRegistryCache.createBundleContextInterceptor(context);
+ }
+ else {
+ return context;
+ }
+ }
+
+ public BundleContext getBundleContext() {
+ return m_context;
+ }
+
+ /**
+ * Adds a new service to the dependency manager. After the service was added
+ * it will be started immediately.
+ *
+ * @param service the service to add
+ */
+ public void add(Component service) {
+ m_components.add(service);
+ service.start();
+ }
+
+ /**
+ * Removes a service from the dependency manager. Before the service is removed
+ * it is stopped first.
+ *
+ * @param service the service to remove
+ */
+ public void remove(Component service) {
+ service.stop();
+ m_components.remove(service);
+ }
+
+ /**
+ * Creates a new service.
+ *
+ * @return the new service
+ */
+ public Component createComponent() {
+ return new ComponentImpl(m_context, this, m_logger);
+ }
+
+ /**
+ * Creates a new service dependency.
+ *
+ * @return the service dependency
+ */
+ public ServiceDependency createServiceDependency() {
+ return new ServiceDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new temporal service dependency.
+ *
+ * @return a new temporal service dependency
+ */
+ public TemporalServiceDependency createTemporalServiceDependency() {
+ return new TemporalServiceDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new configuration dependency.
+ *
+ * @return the configuration dependency
+ */
+ public ConfigurationDependency createConfigurationDependency() {
+ return new ConfigurationDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new configuration property metadata.
+ *
+ * @return the configuration property metadata.
+ */
+ public PropertyMetaData createPropertyMetaData() {
+ return new PropertyMetaDataImpl();
+ }
+
+ /**
+ * Creates a new bundle dependency.
+ *
+ * @return a new BundleDependency instance.
+ */
+ public BundleDependency createBundleDependency() {
+ return new BundleDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new resource dependency.
+ *
+ * @return the resource dependency
+ */
+ public ResourceDependency createResourceDependency() {
+ return new ResourceDependencyImpl(m_context, m_logger);
+ }
+
+ /**
+ * Creates a new aspect. The aspect will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an aspect will be created based on the aspect implementation class.
+ * The aspect will be registered with the same interface and properties
+ * as the original service, plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_service")
+ * .setImplementation(ExistingServiceAspect.class)
+ * );
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the aspect to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param ranking the level used to organize the aspect chain ordering
+ * @param autoConfig the aspect implementation field name where to inject original service.
+ * If null, any field matching the original service will be injected.
+ * @return a service that acts as a factory for generating aspects
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String autoConfig) {
+ return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null);
+ }
+ /**
+ * Creates a new aspect. The aspect will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an aspect will be created based on the aspect implementation class.
+ * The aspect will be registered with the same interface and properties
+ * as the original service, plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAspectService(ExistingService.class, "(foo=bar)", 10)
+ * .setImplementation(ExistingServiceAspect.class)
+ * );
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the aspect to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param ranking the level used to organize the aspect chain ordering
+ * @return a service that acts as a factory for generating aspects
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking) {
+ return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null);
+ }
+ /**
+ * Creates a new aspect. The aspect will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an aspect will be created based on the aspect implementation class.
+ * The aspect will be registered with the same interface and properties
+ * as the original service, plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
+ * .setImplementation(ExistingServiceAspect.class)
+ * );
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the aspect to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param ranking the level used to organize the aspect chain ordering
+ * @param add name of the callback method to invoke on add
+ * @param change name of the callback method to invoke on change
+ * @param remove name of the callback method to invoke on remove
+ * @return a service that acts as a factory for generating aspects
+ */
+ public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove) {
+ return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove);
+ }
+
+ /**
+ * Creates a new adapter. The adapter will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface and existing properties
+ * from the original service plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
+ * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+ * .setImplementation(AdapterImpl.class);
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the adapter to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @return a service that acts as a factory for generating adapters
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null);
+ }
+ /**
+ * Creates a new adapter. The adapter will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface and existing properties
+ * from the original service plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "m_service")
+ * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+ * .setImplementation(AdapterImpl.class);
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the adapter to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param autoConfig the name of the member to inject the service into
+ * @return a service that acts as a factory for generating adapters
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String autoConfig) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null);
+ }
+ /**
+ * Creates a new adapter. The adapter will be applied to any service that
+ * matches the specified interface and filter. For each matching service
+ * an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface and existing properties
+ * from the original service plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
+ * .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+ * .setImplementation(AdapterImpl.class);
+ * </pre></blockquote>
+ *
+ * @param serviceInterface the service interface to apply the adapter to
+ * @param serviceFilter the filter condition to use with the service interface
+ * @param add name of the callback method to invoke on add
+ * @param change name of the callback method to invoke on change
+ * @param remove name of the callback method to invoke on remove
+ * @param swap name of the callback method to invoke on swap
+ * @return a service that acts as a factory for generating adapters
+ */
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove, String swap) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove, swap);
+ }
+
+ public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove) {
+ return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove);
+ }
+
+ /**
+ * Creates a new resource adapter. The adapter will be applied to any resource that
+ * matches the specified filter condition. For each matching resource
+ * an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface and existing properties
+ * from the original resource plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createResourceAdapterService("(&(path=/test)(repository=TestRepository))", true)
+ * // The interface to use when registering adapter
+ * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+ * // the implementation of the adapter
+ * .setImplementation(AdapterServiceImpl.class);
+ * </pre></blockquote>
+ *
+ * @param resourceFilter the filter condition to use with the resource
+ * @param resourcePropertiesFilter the filter condition on the resource properties to use with the resource
+ * @param propagate <code>true</code> if properties from the resource should be propagated to the service
+ * @param callbackInstance
+ * @param callbackChanged
+ * @return a service that acts as a factory for generating resource adapters
+ * @see Resource
+ */
+ public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackChanged) {
+ return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, null, callbackChanged);
+ }
+
+ public Component createResourceAdapterService(String resourceFilter, boolean propagate, Object callbackInstance, String callbackSet, String callbackChanged) {
+ return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, callbackSet, callbackChanged);
+ }
+
+ public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
+ return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, null, callbackChanged);
+ }
+
+ public Component createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackSet, String callbackChanged) {
+ return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, callbackSet, callbackChanged);
+ }
+
+ /**
+ * Creates a new bundle adapter. The adapter will be applied to any bundle that
+ * matches the specified bundle state mask and filter condition. For each matching
+ * bundle an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface
+ *
+ * TODO and existing properties from the original resource plus any extra properties you supply here.
+ * It will also inherit all dependencies, and if you declare the original
+ * service as a member it will be injected.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createBundleAdapterService(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE,
+ * "(Bundle-SymbolicName=org.apache.felix.dependencymanager)",
+ * true)
+ * // The interface to use when registering adapter
+ * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+ * // the implementation of the adapter
+ * .setImplementation(AdapterServiceImpl.class);
+ * </pre></blockquote>
+ *
+ * @param bundleStateMask the bundle state mask to apply
+ * @param bundleFilter the filter to apply to the bundle manifest
+ * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
+ * @return a service that acts as a factory for generating bundle adapters
+ */
+ public Component createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
+ return new BundleAdapterServiceImpl(this, bundleStateMask, bundleFilter, propagate);
+ }
+
+ /**
+ * Creates a new Managed Service Factory Configuration Adapter. For each new Config Admin factory configuration matching
+ * the factoryPid, an adapter will be created based on the adapter implementation class.
+ * The adapter will be registered with the specified interface, and with the specified adapter service properties.
+ * Depending on the <code>propagate</code> parameter, every public factory configuration properties
+ * (which don't start with ".") will be propagated along with the adapter service properties.
+ * It will also inherit all dependencies.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * manager.createFactoryConfigurationAdapterService("MyFactoryPid", "update", true)
+ * // The interface to use when registering adapter
+ * .setInterface(AdapterService.class.getName(), new Hashtable() {{ put("foo", "bar"); }})
+ * // the implementation of the adapter
+ * .setImplementation(AdapterServiceImpl.class);
+ * </pre></blockquote>
+ *
+ * @param factoryPid the pid matching the factory configuration
+ * @param update the adapter method name that will be notified when the factory configuration is created/updated.
+ * @param propagate true if public factory configuration should be propagated to the adapter service properties
+ * @return a service that acts as a factory for generating the managed service factory configuration adapter
+ */
+ public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate) {
+ return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate);
+ }
+
+ /**
+ * Creates a new Managed Service Factory Configuration Adapter with meta type support. For each new Config Admin
+ * factory configuration matching the factoryPid, an adapter will be created based on the adapter implementation
+ * class. The adapter will be registered with the specified interface, and with the specified adapter service
+ * properties. Depending on the <code>propagate</code> parameter, every public factory configuration properties
+ * (which don't start with ".") will be propagated along with the adapter service properties.
+ * It will also inherit all dependencies.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * <blockquote><pre>
+ * PropertyMetaData[] propertiesMetaData = new PropertyMetaData[] {
+ * manager.createPropertyMetaData()
+ * .setCardinality(Integer.MAX_VALUE)
+ * .setType(String.class)
+ * .setHeading("English words")
+ * .setDescription("Declare here some valid english words")
+ * .setDefaults(new String[] {"hello", "world"})
+ * .setId("words")
+ * };
+ *
+ * manager.add(createFactoryConfigurationAdapterService("FactoryPid",
+ * "updated",
+ * true, // propagate CM settings
+ * "EnglishDictionary",
+ * "English dictionary configuration properties",
+ * null,
+ * propertiesMetaData)
+ * .setImplementation(Adapter.class));
+ * </pre></blockquote>
+ *
+ * @param factoryPid the pid matching the factory configuration
+ * @param update the adapter method name that will be notified when the factory configuration is created/updated.
+ * @param propagate true if public factory configuration should be propagated to the adapter service properties
+ * @param heading The label used to display the tab name (or section) where the properties are displayed.
+ * Example: "Printer Service"
+ * @param desc A human readable description of the factory PID this configuration is associated with.
+ * Example: "Configuration for the PrinterService bundle"
+ * @param localization Points to the basename of the Properties file that can localize the Meta Type informations.
+ * The default localization base name for the properties is OSGI-INF/l10n/bundle, but can
+ * be overridden by the manifest Bundle-Localization header (see core specification, in section Localization
+ * on page 68). You can specify a specific localization basename file using this parameter
+ * (e.g. <code>"person"</code> will match person_du_NL.properties in the root bundle directory).
+ * @param propertiesMetaData Array of MetaData regarding configuration properties
+ * @return a service that acts as a factory for generating the managed service factory configuration adapter
+ */
+ public Component createFactoryConfigurationAdapterService(String factoryPid, String update, boolean propagate,
+ String heading, String desc, String localization,
+ PropertyMetaData[] propertiesMetaData)
+ {
+ return new FactoryConfigurationAdapterServiceImpl(this, factoryPid, update, propagate, m_context, m_logger,
+ heading, desc, localization, propertiesMetaData);
+ }
+
+ /**
+ * Returns a list of services.
+ *
+ * @return a list of services
+ */
+ public List getComponents() {
+ return Collections.unmodifiableList(m_components);
+ }
+
+ /**
+ * Removes all components and their dependencies.
+ */
+ public void clear() {
+ List services = getComponents();
+ for (int i = services.size() - 1; i >= 0; i--) {
+ Component service = (Component) services.get(i);
+ remove(service);
+ // remove any state listeners that are still registered
+ if (service instanceof ComponentImpl) {
+ ComponentImpl si = (ComponentImpl) service;
+ si.removeStateListeners();
+ }
+ }
+ }
+
+}
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface DependencyService {
+ /**
+ * Will be called when the dependency becomes available.
+ *
+ * @param dependency the dependency
+ */
+ public void dependencyAvailable(Dependency dependency);
+
+ /**
+ * Will be called when the dependency changes.
+ *
+ * @param dependency the dependency
+ */
+ public void dependencyUnavailable(Dependency dependency);
+
+ /**
+ * Will be called when the dependency becomes unavailable.
+ *
+ * @param dependency the dependency
+ */
+ public void dependencyChanged(Dependency dependency);
+
+ public Object getService(); // is also defined on the Service interface
+ public void initService(); // was an implementation method TODO we use it in ConfDepImpl but should not (probably)
+ public boolean isRegistered(); // impl method
+ public Object[] getCompositionInstances(); // impl method
+
+ public boolean isInstantiated();
+
+ /**
+ * Can be called by the dependency whenever it wants to invoke callback methods.
+ */
+ public void invokeCallbackMethod(Object[] instances, String methodName, Class[][] signatures, Object[][] parameters);
+
+ public Component getServiceInterface();
+}
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.util.List;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+
+/**
+ * A filter index is an interface you can implement to create your own, optimized index for specific filter expressions.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface FilterIndex {
+ /** Opens this filter index. */
+ public void open(BundleContext context);
+ /** Closes this filter index. */
+ public void close();
+ /** Determines if the combination of class and filter is applicable for this filter index. */
+ public boolean isApplicable(String clazz, String filter);
+ /** Returns all service references that match the specified class and filter. */
+ public List /* <ServiceReference> */ getAllServiceReferences(String clazz, String filter);
+ /** Invoked whenever a service event occurs. */
+ public void serviceChanged(ServiceEvent event);
+ /** Adds a service listener to this filter index. */
+ public void addServiceListener(ServiceListener listener, String filter);
+ /** Removes a service listener from this filter index. */
+ public void removeServiceListener(ServiceListener listener);
+}
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/InvocationUtil.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class InvocationUtil {
+ private static final Map /* <Key, Method> */ m_methodCache;
+ static {
+ int size = 2048;
+ try {
+ String value = System.getProperty(DependencyManager.METHOD_CACHE_SIZE);
+ if (value != null) {
+ size = Integer.parseInt(value);
+ }
+ }
+ catch (Exception e) {}
+ m_methodCache = new LRUMap(Math.max(size, 64));
+ }
+
+ public static Object invokeCallbackMethod(Object instance, String methodName, Class[][] signatures, Object[][] parameters) throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+ Class currentClazz = instance.getClass();
+ while (currentClazz != null) {
+ try {
+ return invokeMethod(instance, currentClazz, methodName, signatures, parameters, false);
+ }
+ catch (NoSuchMethodException nsme) {
+ // ignore
+ }
+ currentClazz = currentClazz.getSuperclass();
+ }
+ throw new NoSuchMethodException(methodName);
+ }
+
+ public static Object invokeMethod(Object object, Class clazz, String name, Class[][] signatures, Object[][] parameters, boolean isSuper) throws NoSuchMethodException, InvocationTargetException, IllegalArgumentException, IllegalAccessException {
+ if (object == null) {
+ throw new IllegalArgumentException("Instance cannot be null");
+ }
+ if (clazz == null) {
+ throw new IllegalArgumentException("Class cannot be null");
+ }
+
+ // if we're talking to a proxy here, dig one level deeper to expose the
+ // underlying invocation handler (we do the same for injecting instances)
+ if (Proxy.isProxyClass(clazz)) {
+ object = Proxy.getInvocationHandler(object);
+ clazz = object.getClass();
+ }
+
+ Method m = null;
+ for (int i = 0; i < signatures.length; i++) {
+ Class[] signature = signatures[i];
+ m = getDeclaredMethod(clazz, name, signature, isSuper);
+ if (m != null) {
+ return m.invoke(object, parameters[i]);
+ }
+ }
+ throw new NoSuchMethodException(name);
+ }
+
+ private static Method getDeclaredMethod(Class clazz, String name, Class[] signature, boolean isSuper) {
+ // first check our cache
+ Key key = new Key(clazz, name, signature);
+ Method m = null;
+ synchronized (m_methodCache) {
+ m = (Method) m_methodCache.get(key);
+ if (m != null) {
+ return m;
+ }
+ else if (m_methodCache.containsKey(key)) {
+ // the key is in our cache, it just happens to have a null value
+ return null;
+ }
+ }
+ // then do a lookup
+ try {
+ m = clazz.getDeclaredMethod(name, signature);
+ if (!(isSuper && Modifier.isPrivate(m.getModifiers()))) {
+ m.setAccessible(true);
+ }
+ }
+ catch (NoSuchMethodException e) {
+ // ignore
+ }
+ synchronized (m_methodCache) {
+ m_methodCache.put(key, m);
+ }
+ return m;
+ }
+
+ public static class Key {
+ private final Class m_clazz;
+ private final String m_name;
+ private final Class[] m_signature;
+
+ public Key(Class clazz, String name, Class[] signature) {
+ m_clazz = clazz;
+ m_name = name;
+ m_signature = signature;
+ }
+
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((m_clazz == null) ? 0 : m_clazz.hashCode());
+ result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
+ result = prime * result + Arrays.hashCode(m_signature);
+ return result;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Key other = (Key) obj;
+ if (m_clazz == null) {
+ if (other.m_clazz != null)
+ return false;
+ }
+ else if (!m_clazz.equals(other.m_clazz))
+ return false;
+ if (m_name == null) {
+ if (other.m_name != null)
+ return false;
+ }
+ else if (!m_name.equals(other.m_name))
+ return false;
+ if (!Arrays.equals(m_signature, other.m_signature))
+ return false;
+ return true;
+ }
+ }
+
+ public static class LRUMap extends LinkedHashMap {
+ private final int m_size;
+
+ public LRUMap(int size) {
+ m_size = size;
+ }
+
+ protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
+ return size() > m_size;
+ }
+ }
+}
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/PropertyMetaData.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless
+ * required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+/**
+ * This interface defines meta data regarding a given configuration property.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface PropertyMetaData {
+ /**
+ * The label used to display the property. Example: "Log Level".
+ * @return The label used to display the property (may be localized)
+ */
+ public PropertyMetaData setHeading(String heading);
+
+ /**
+ * The key of a ConfigurationAdmin property. Example: "printer.logLevel"
+ * @return The Configuration Admin property name
+ */
+ public PropertyMetaData setId(String id);
+
+ /**
+ * Returns the property primitive type. If must be either one of the following types:<p>
+ * <ul>
+ * <li>String.class</li>
+ * <li>Long.class</li>
+ * <li>Integer.class</li>
+ * <li>Character.class</li>
+ * <li>Byte.class</li>
+ * <li>Double.class</li>
+ * <li>Float.class</li>
+ * <li>Boolean.class</li>
+ * </ul>
+ */
+ public PropertyMetaData setType(Class type);
+
+ /**
+ * Returns a default for this property. The object must be of the appropriate type as defined by the cardinality and getType().
+ * The return type is a list of String objects that can be converted to the appropriate type. The cardinality of the return
+ * array must follow the absolute cardinality of this type. E.g. if the cardinality = 0, the array must contain 1 element.
+ * If the cardinality is 1, it must contain 0 or 1 elements. If it is -5, it must contain from 0 to max 5 elements. Note that
+ * the special case of a 0 cardinality, meaning a single value, does not allow arrays or vectors of 0 elements.
+ */
+ public PropertyMetaData setDefaults(String[] defaults);
+
+ /**
+ * Returns the property description. The description may be localized and must describe the semantics of this type and any
+ * constraints. Example: "Select the log level for the Printer Service".
+ * @return a localizable description of the property.
+ */
+ public PropertyMetaData setDescription(String description);
+
+ /**
+ * Return the cardinality of this property. The OSGi environment handles multi valued properties in arrays ([]) or in Vector objects.
+ * The return value is defined as follows:<p>
+ *
+ * <ul>
+ * <li> x = Integer.MIN_VALUE no limit, but use Vector</li>
+ * <li> x < 0 -x = max occurrences, store in Vector</li>
+ * <li> x > 0 x = max occurrences, store in array []</li>
+ * <li> x = Integer.MAX_VALUE no limit, but use array []</li>
+ * <li> x = 0 1 occurrence required</li>
+ * </ul>
+ */
+ public PropertyMetaData setCardinality(int cardinality);
+
+ /**
+ * Tells if this property is required or not.
+ */
+ public PropertyMetaData setRequired(boolean required);
+
+ /**
+ * Return a list of valid options for this property (the labels may be localized).
+ * @return the list of valid options for this property.
+ */
+ public PropertyMetaData addOption(String optionLabel, String optionValue);
+}
\ No newline at end of file
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.net.URL;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ResourceDependency extends Dependency, ComponentDependencyDeclaration, ResourceHandler {
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added or removed. When you specify callbacks, the auto configuration
+ * feature is automatically turned off, because we're assuming you don't need it in this
+ * case.
+ *
+ * @param added the method to call when a service was added
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ResourceDependency setCallbacks(String added, String removed) ;
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added, changed or removed. When you specify callbacks, the auto
+ * configuration feature is automatically turned off, because we're assuming you don't
+ * need it in this case.
+ *
+ * @param added the method to call when a service was added
+ * @param changed the method to call when a service was changed
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ResourceDependency setCallbacks(String added, String changed, String removed);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added or removed. They are called on the instance you provide. When you
+ * specify callbacks, the auto configuration feature is automatically turned off, because
+ * we're assuming you don't need it in this case.
+ *
+ * @param instance the instance to call the callbacks on
+ * @param added the method to call when a service was added
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ResourceDependency setCallbacks(Object instance, String added, String removed);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added, changed or removed. They are called on the instance you provide. When you
+ * specify callbacks, the auto configuration feature is automatically turned off, because
+ * we're assuming you don't need it in this case.
+ *
+ * @param instance the instance to call the callbacks on
+ * @param added the method to call when a service was added
+ * @param changed the method to call when a service was changed
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ResourceDependency setCallbacks(Object instance, String added, String changed, String removed);
+
+ /**
+ * Sets auto configuration for this service. Auto configuration allows the
+ * dependency to fill in any attributes in the service implementation that
+ * are of the same type as this dependency. Default is on.
+ *
+ * @param autoConfig the value of auto config
+ * @return this service dependency
+ */
+ public ResourceDependency setAutoConfig(boolean autoConfig);
+
+ /**
+ * Sets auto configuration for this service. Auto configuration allows the
+ * dependency to fill in the attribute in the service implementation that
+ * has the same type and instance name.
+ *
+ * @param instanceName the name of attribute to auto config
+ * @return this service dependency
+ */
+ public ResourceDependency setAutoConfig(String instanceName);
+
+ public ResourceDependency setResource(URL resource);
+
+ public ResourceDependency setRequired(boolean required);
+
+ public ResourceDependency setFilter(String resourceFilter);
+
+ public ResourceDependency setPropagate(boolean propagate);
+
+ public ResourceDependency setPropagate(Object instance, String method);
+
+ public ResourceDependency setInstanceBound(boolean isInstanceBound);
+}
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceHandler.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.net.URL;
+import java.util.Dictionary;
+
+/**
+ * Service interface for anybody wanting to be notified of changes to resources.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ResourceHandler {
+ /** Name of the property that's used to describe the filter condition for a resource. */
+ public static final String FILTER = "filter";
+ /** Exact URL that this handler is looking for. Can be used instead of a filter to be very explicit about the resource you're looking for. */
+ public static final String URL = "url";
+ /** The host part of the URL. */
+ public static final String HOST = "host";
+ /** The path part of the URL. */
+ public static final String PATH = "path";
+ /** The protocol part of the URL. */
+ public static final String PROTOCOL = "protocol";
+ /** The port part of the URL. */
+ public static final String PORT = "port";
+
+ /**
+ * @deprecated Please use {@link #added(URL, Dictionary)} instead. When both are specified,
+ * the new method takes precedence and the deprecated one is not invoked.
+ */
+ public void added(URL resource);
+
+ /**
+ * Invoked whenever a new resource is added.
+ */
+ public void added(URL resource, Dictionary resourceProperties);
+
+ /**
+ * @deprecated Please use {@link #changed(URL, Dictionary)} instead. When both are specified,
+ * the new method takes precedence and the deprecated one is not invoked.
+ */
+ public void changed(URL resource);
+
+ /**
+ * Invoked whenever an existing resource changes.
+ */
+ public void changed(URL resource, Dictionary resourceProperties);
+
+ /**
+ * @deprecated Please use {@link #removed(URL, Dictionary)} instead. When both are specified,
+ * the new method takes precedence and the deprecated one is not invoked.
+ */
+ public void removed(URL resource);
+
+ /**
+ * Invoked whenever an existing resource is removed.
+ */
+ public void removed(URL resource, Dictionary resourceProperties);
+}
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceUtil.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Properties;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ResourceUtil {
+ public static Dictionary createProperties(URL url) {
+ Properties props = new Properties();
+ props.setProperty(ResourceHandler.PROTOCOL, url.getProtocol());
+ props.setProperty(ResourceHandler.HOST, url.getHost());
+ props.setProperty(ResourceHandler.PORT, Integer.toString(url.getPort()));
+ props.setProperty(ResourceHandler.PATH, url.getPath());
+ return props;
+ }
+}
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Service dependency that can track an OSGi service.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ServiceDependency extends Dependency, ComponentDependencyDeclaration {
+ /**
+ * Sets the name of the service that should be tracked.
+ *
+ * @param serviceName the name of the service
+ * @return this service dependency
+ */
+ public ServiceDependency setService(Class serviceName);
+
+ /**
+ * Sets the name of the service that should be tracked. You can either specify
+ * only the name, or the name and a filter. In the latter case, the filter is used
+ * to track the service and should only return services of the type that was specified
+ * in the name. To make sure of this, the filter is actually extended internally to
+ * filter on the correct name.
+ *
+ * @param serviceName the name of the service
+ * @param serviceFilter the filter condition
+ * @return this service dependency
+ */
+ public ServiceDependency setService(Class serviceName, String serviceFilter);
+
+ /**
+ * Sets the filter for the services that should be tracked. Any service object
+ * matching the filter will be returned, without any additional filter on the
+ * class.
+ *
+ * @param serviceFilter the filter condition
+ * @return this service dependency
+ */
+ public ServiceDependency setService(String serviceFilter);
+
+ /**
+ * Sets the name of the service that should be tracked. You can either specify
+ * only the name, or the name and a reference. In the latter case, the service reference
+ * is used to track the service and should only return services of the type that was
+ * specified in the name.
+ *
+ * @param serviceName the name of the service
+ * @param serviceReference the service reference to track
+ * @return this service dependency
+ */
+ public ServiceDependency setService(Class serviceName, ServiceReference serviceReference);
+
+ /**
+ * Sets the default implementation for this service dependency. You can use this to supply
+ * your own implementation that will be used instead of a Null Object when the dependency is
+ * not available. This is also convenient if the service dependency is not an interface
+ * (which would cause the Null Object creation to fail) but a class.
+ *
+ * @param implementation the instance to use or the class to instantiate if you want to lazily
+ * instantiate this implementation
+ * @return this service dependency
+ */
+ public ServiceDependency setDefaultImplementation(Object implementation);
+
+ /**
+ * Sets the required flag which determines if this service is required or not.
+ *
+ * @param required the required flag
+ * @return this service dependency
+ */
+ public ServiceDependency setRequired(boolean required);
+
+ /**
+ * Sets auto configuration for this service. Auto configuration allows the
+ * dependency to fill in any attributes in the service implementation that
+ * are of the same type as this dependency. Default is on.
+ *
+ * @param autoConfig the value of auto config
+ * @return this service dependency
+ */
+ public ServiceDependency setAutoConfig(boolean autoConfig);
+
+ /**
+ * Sets auto configuration for this service. Auto configuration allows the
+ * dependency to fill in the attribute in the service implementation that
+ * has the same type and instance name.
+ *
+ * @param instanceName the name of attribute to auto config
+ * @return this service dependency
+ */
+ public ServiceDependency setAutoConfig(String instanceName);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added or removed. When you specify callbacks, the auto configuration
+ * feature is automatically turned off, because we're assuming you don't need it in this
+ * case.
+ *
+ * @param added the method to call when a service was added
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ServiceDependency setCallbacks(String added, String removed);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added, changed or removed. When you specify callbacks, the auto
+ * configuration feature is automatically turned off, because we're assuming you don't
+ * need it in this case.
+ *
+ * @param added the method to call when a service was added
+ * @param changed the method to call when a service was changed
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ServiceDependency setCallbacks(String added, String changed, String removed);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added, changed or removed. When you specify callbacks, the auto
+ * configuration feature is automatically turned off, because we're assuming you don't
+ * need it in this case.
+ * @param added the method to call when a service was added
+ * @param changed the method to call when a service was changed
+ * @param removed the method to call when a service was removed
+ * @param swapped the method to call when the service was swapped due to addition or
+ * removal of an aspect
+ * @return this service dependency
+ */
+ public ServiceDependency setCallbacks(String added, String changed, String removed, String swapped);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added or removed. They are called on the instance you provide. When you
+ * specify callbacks, the auto configuration feature is automatically turned off, because
+ * we're assuming you don't need it in this case.
+ *
+ * @param instance the instance to call the callbacks on
+ * @param added the method to call when a service was added
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ServiceDependency setCallbacks(Object instance, String added, String removed);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added, changed or removed. They are called on the instance you provide. When you
+ * specify callbacks, the auto configuration feature is automatically turned off, because
+ * we're assuming you don't need it in this case.
+ *
+ * @param instance the instance to call the callbacks on
+ * @param added the method to call when a service was added
+ * @param changed the method to call when a service was changed
+ * @param removed the method to call when a service was removed
+ * @return this service dependency
+ */
+ public ServiceDependency setCallbacks(Object instance, String added, String changed, String removed);
+
+ /**
+ * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+ * dependency is added, changed or removed. When you specify callbacks, the auto
+ * configuration feature is automatically turned off, because we're assuming you don't
+ * need it in this case.
+ * @param instance the instance to call the callbacks on
+ * @param added the method to call when a service was added
+ * @param changed the method to call when a service was changed
+ * @param removed the method to call when a service was removed
+ * @param swapped the method to call when the service was swapped due to addition or
+ * removal of an aspect
+ * @return this service dependency
+ */
+ public ServiceDependency setCallbacks(Object instance, String added, String changed, String removed, String swapped);
+
+ /**
+ * Sets propagation of the service dependency properties to the provided service properties. Any additional
+ * service properties specified directly are merged with these.
+ */
+ public ServiceDependency setPropagate(boolean propagate);
+
+ /**
+ * Sets an Object instance and a callback method used to propagate some properties to the provided service properties.
+ * The method will be invoked on the specified object instance and must have one of the following signatures:<p>
+ * <ul><li>Dictionary callback(ServiceReference, Object service)
+ * <li>Dictionary callback(ServiceReference)
+ * </ul>
+ * @param instance the Object instance which is used to retrieve propagated service properties
+ * @param method the method to invoke for retrieving the properties to be propagated to the service properties.
+ * @return this service dependency.
+ */
+ public ServiceDependency setPropagate(Object instance, String method);
+
+ public ServiceDependency setInstanceBound(boolean isInstanceBound);
+}
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceUtil.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceUtil.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceUtil.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+import java.util.List;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * OSGi service utilities.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceUtil {
+ /**
+ * Returns the service ranking of a service, based on its service reference. If
+ * the service has a property specifying its ranking, that will be returned. If
+ * not, the default ranking of zero will be returned.
+ *
+ * @param ref the service reference to determine the ranking for
+ * @return the ranking
+ */
+ public static int getRanking(ServiceReference ref) {
+ return getRankingAsInteger(ref).intValue();
+ }
+
+ /**
+ * Returns the service ranking of a service, based on its service reference. If
+ * the service has a property specifying its ranking, that will be returned. If
+ * not, the default ranking of zero will be returned.
+ *
+ * @param ref the service reference to determine the ranking for
+ * @return the ranking
+ */
+ public static Integer getRankingAsInteger(ServiceReference ref) {
+ Integer rank = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+ if (rank != null) {
+ return rank;
+ }
+ return new Integer(0);
+ }
+
+ /**
+ * Returns the service ID of a service, based on its service reference. This
+ * method is aware of service aspects as defined by the dependency manager and
+ * will return the ID of the orginal service if you give it an aspect.
+ *
+ * @param ref the service reference to determine the service ID of
+ * @return the service ID
+ */
+ public static long getServiceId(ServiceReference ref) {
+ return getServiceIdAsLong(ref).longValue();
+ }
+
+ /**
+ * Returns the service ID of a service, based on its service reference. This
+ * method is aware of service aspects as defined by the dependency manager and
+ * will return the ID of the orginal service if you give it an aspect.
+ *
+ * @param ref the service reference to determine the service ID of
+ * @return the service ID
+ */
+ public static Long getServiceIdAsLong(ServiceReference ref) {
+ return getServiceIdObject(ref);
+ }
+
+ public static Long getServiceIdObject(ServiceReference ref) {
+ Long aid = (Long) ref.getProperty(DependencyManager.ASPECT);
+ if (aid != null) {
+ return aid;
+ }
+ Long sid = (Long) ref.getProperty(Constants.SERVICE_ID);
+ if (sid != null) {
+ return sid;
+ }
+ throw new IllegalArgumentException("Invalid service reference, no service ID found");
+ }
+
+ /**
+ * Determines if the service is an aspect as defined by the dependency manager.
+ * Aspects are defined by a property and this method will check for its presence.
+ *
+ * @param ref the service reference
+ * @return <code>true</code> if it's an aspect, <code>false</code> otherwise
+ */
+ public static boolean isAspect(ServiceReference ref) {
+ Long aid = (Long) ref.getProperty(DependencyManager.ASPECT);
+ return (aid != null);
+ }
+
+ /**
+ * Converts a service reference to a string, listing both the bundle it was
+ * registered from and all properties.
+ *
+ * @param ref the service reference
+ * @return a string representation of the service
+ */
+ public static String toString(ServiceReference ref) {
+ if (ref == null) {
+ return "ServiceReference[null]";
+ }
+ else {
+ StringBuffer buf = new StringBuffer();
+ Bundle bundle = ref.getBundle();
+ if (bundle != null) {
+ buf.append("ServiceReference[");
+ buf.append(bundle.getBundleId());
+ buf.append("]{");
+ }
+ else {
+ buf.append("ServiceReference[unregistered]{");
+ }
+ buf.append(propertiesToString(ref, null));
+ buf.append("}");
+ return buf.toString();
+ }
+ }
+
+ /**
+ * Converts the properties of a service reference to a string.
+ *
+ * @param ref the service reference
+ * @param exclude a list of properties to exclude, or <code>null</code> to show everything
+ * @return a string representation of the service properties
+ */
+ public static String propertiesToString(ServiceReference ref, List /* <String> */ exclude) {
+ StringBuffer buf = new StringBuffer();
+ String[] keys = ref.getPropertyKeys();
+ for (int i = 0; i < keys.length; i++) {
+ if (i > 0) {
+ buf.append(',');
+ }
+ buf.append(keys[i]);
+ buf.append('=');
+ Object val = ref.getProperty(keys[i]);
+ if (exclude == null || !exclude.contains(val)) {
+ if (val instanceof String[]) {
+ String[] valArray = (String[]) val;
+ StringBuffer valBuf = new StringBuffer();
+ valBuf.append('{');
+ for (int j = 0; j < valArray.length; j++) {
+ if (valBuf.length() > 1) {
+ valBuf.append(',');
+ }
+ valBuf.append(valArray[j].toString());
+ }
+ valBuf.append('}');
+ buf.append(valBuf);
+ }
+ else {
+ buf.append(val.toString());
+ }
+ }
+ }
+ return buf.toString();
+ }
+}
Added: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/TemporalServiceDependency.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/TemporalServiceDependency.java?rev=1293173&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/TemporalServiceDependency.java (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/TemporalServiceDependency.java Fri Feb 24 10:47:49 2012
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless
+ * required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm;
+
+/**
+ * A Temporal Service dependency that can block the caller thread between service updates. Only useful for required stateless
+ * dependencies that can be replaced transparently. A Dynamic Proxy is used to wrap the actual service dependency. When the
+ * dependency goes away, an attempt is made to replace it with another one which satisfies the service dependency criteria. If
+ * no service replacement is available, then any method invocation (through the dynamic proxy) will block during a configurable
+ * timeout. On timeout, an unchecked <code>IllegalStateException</code> exception is raised (but the service is not
+ * deactivated).
+ * <p>
+ * <b>This class only supports required dependencies, and temporal dependencies must be accessed outside the Activator (OSGi)
+ * thread, because method invocations may block the caller thread when dependencies are not satisfied. </b>
+ * <p>
+ * Sample Code:
+ * <p>
+ * <blockquote>
+ *
+ * <pre>
+ * import org.apache.felix.dependencymanager.*;
+ *
+ * public class Activator extends DependencyActivatorBase {
+ * public void init(BundleContext ctx, DependencyManager dm) throws Exception {
+ * dm.add(createService()
+ * .setImplementation(MyServer.class)
+ * .add(createTemporalServiceDependency()
+ * .setTimeout(15000)
+ * .setService(MyDependency.class)));
+ * }
+ *
+ * public void destroy(BundleContext ctx, DependencyManager dm) throws Exception {
+ * }
+ * }
+ *
+ * class MyServer implements Runnable {
+ * MyDependency _dependency; // Auto-Injected by reflection.
+ * void start() {
+ * (new Thread(this)).start();
+ * }
+ *
+ * public void run() {
+ * try {
+ * _dependency.doWork();
+ * } catch (IllegalStateException e) {
+ * t.printStackTrace();
+ * }
+ * }
+ * </pre>
+ *
+ * </blockquote>
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface TemporalServiceDependency extends ServiceDependency {
+ /**
+ * Sets the timeout for this temporal dependency. Specifying a timeout value of zero means that there is no timeout period,
+ * and an invocation on a missing service will fail immediately.
+ *
+ * @param timeout the dependency timeout value greater or equals to 0
+ * @throws IllegalArgumentException if the timeout is negative
+ * @return this temporal dependency
+ */
+ TemporalServiceDependency setTimeout(long timeout);
+}