blob: 334447cba11b9b15cd77b9b929de3b0fc8f306ef [file] [log] [blame]
/*
* 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.annotation.versioning.ProviderType;
import org.osgi.framework.ServiceReference;
/**
* Service dependency that can track an OSGi service.
*
* When defining dependency method callbacks; for "add", "change", "remove" callbacks, the following method signatures are supported:
*
* <pre>{@code
* (Component comp, ServiceReference ref, Service service)
* (Component comp, ServiceReference ref, Object service)
* (Component comp, ServiceReference ref)
* (Component comp, Service service)
* (Component comp, Object service)
* (Component comp)
* (Component comp, Map properties, Service service)
* (ServiceReference ref, Service service)
* (ServiceReference ref, Object service)
* (ServiceReference ref)
* (Service service)
* (Service service, Map propeerties)
* (Map properties, Service, service)
* (Service service, Dictionary properties)
* (Dictionary properties, Service service)
* (Object service)
* (ServiceObjects service)
* }</pre>
*
* <p> For "swap" callbacks, the following method signatures are supported:
*
* <pre>{@code
* (Service old, Service replace)
* (Object old, Object replace)
* (ServiceReference old, Service old, ServiceReference replace, Service replace)
* (ServiceReference old, Object old, ServiceReference replace, Object replace)
* (Component comp, Service old, Service replace)
* (Component comp, Object old, Object replace)
* (Component comp, ServiceReference old, Service old, ServiceReference replace, Service replace)
* (Component comp, ServiceReference old, Object old, ServiceReference replace, Object replace)
* (ServiceReference old, ServiceReference replace)
* (Component comp, ServiceReference old, ServiceReference replace)
* (ServiceObjects old, ServiceObjects replace)
* (Component comp, ServiceObjects old, ServiceObjects replace)
* }</pre>
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
@ProviderType
public interface ServiceDependency extends Dependency, ComponentDependencyDeclaration {
/**
* 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 add the method to call when a service was added
* @param remove the method to call when a service was removed
* @return this service dependency
*/
public ServiceDependency setCallbacks(String add, String remove);
/**
* 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 add the method to call when a service was added
* @param change the method to call when a service was changed
* @param remove the method to call when a service was removed
* @return this service dependency
*/
public ServiceDependency setCallbacks(String add, String change, String remove);
/**
* 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 add the method to call when a service was added
* @param change the method to call when a service was changed
* @param remove the method to call when a service was removed
* @param swap 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 add, String change, String remove, String swap);
/**
* 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 add the method to call when a service was added
* @param remove the method to call when a service was removed
* @return this service dependency
*/
public ServiceDependency setCallbacks(Object instance, String add, String remove);
/**
* 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 add the method to call when a service was added
* @param change the method to call when a service was changed
* @param remove the method to call when a service was removed
* @return this service dependency
*/
public ServiceDependency setCallbacks(Object instance, String add, String change, String remove);
/**
* 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 the required flag which determines if this service is required or not.
* A ServiceDependency is false by default.
*
* @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 the attribute in the service implementation that
* has the same type and instance name. Dependency services will be injected
* in the following kind of fields:<p>
* <ul>
* <li> a field having the same type as the dependency. If the field may be accessed by anythread, then
* the field should be declared volatile, in order to ensure visibility when the field is auto injected concurrently.
*
* <li> a field which is assignable to an <code>Iterable&#60;T&#62;</code> where T must match the dependency type.
* In this case, an Iterable will be injected by DependencyManager before the start callback is called.
* The Iterable field may then be traversed to inspect the currently available dependency services. The Iterable
* can possibly be set to a final value so you can choose the Iterable implementation of your choice
* (for example, a CopyOnWrite ArrayList, or a ConcurrentLinkedQueue).
*
* <li> a <code>Map&#60;K,V&#62;</code> where K must match the dependency type and V must exactly be equal to <code>Dictionary</code>.
* In this case, a ConcurrentHashMap will be injected by DependencyManager before the start callback is called.
* The Map may then be consulted to lookup current available dependency services, including the dependency service
* properties (the map key holds the dependency service, and the map value holds the dependency service properties).
*
* The Map field may be set to a final value so you can choose a Map of your choice (Typically a ConcurrentHashMap).
*
* A ConcurrentHashMap is "weakly consistent", meaning that when traversing
* the elements, you may or may not see any concurrent updates made on the map. So, take care to traverse
* the map using an iterator on the map entry set, which allows to atomically lookup pairs of Dependency service/Service properties.
* </ul>
*
* <p> Here are some example using an Iterable:
* <blockquote>
*
* <pre>
*
* public class SpellChecker {
* // can be traversed to inspect currently available dependencies
* final Iterable&#60;DictionaryService&#62; dictionaries = new ConcurrentLinkedQueue<>();
*
* Or
*
* // will be injected by DM automatically and can be traversed any time to inspect all currently available dependencies.
* volatile Iterable&#60;DictionaryService&#62; dictionaries = null;
* }
*
* </pre>
* </blockquote>
*
* Here are some example using a Map:
* <blockquote>
*
* <pre>
*
* public class SpellChecker {
* // can be traversed to inspect currently available dependencies
* final Map&#60;DictionaryService, Dictionary&#62; dictionaries = new ConcurrentLinkedQueue<>();
*
* or
*
* // will be injected by DM automatically and can be traversed to inspect currently available dependencies
* volatile Map&#60;DictionaryService, Dictionary&#62; dictionaries = null;
*
* void iterateOnAvailableServices() {
* for (Map.Entry<MyService, Dictionary> entry : this.services.entrySet()) {
* MyService currentService = entry.getKey();
* Dictionary currentServiceProperties = entry.getValue();
* // ...
* }
* }
* }
*
* </pre>
* </blockquote>
*
* @param autoConfig the name of attribute to auto configure
* @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
* @see #setAutoConfig(boolean)
*/
public ServiceDependency setAutoConfig(String instanceName);
/**
* 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
*/
@SuppressWarnings("rawtypes")
public ServiceDependency setService(Class<?> serviceName, ServiceReference serviceReference);
/**
* Sets the default implementation for an <code>optional</code> 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.
* Only use this attribute on an optional service dependency injected on a class field.
*
* @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 propagation of the service dependency properties to the provided service properties. Any additional
* service properties specified directly are merged with these. The provided service properties take precedence over the
* propagated service dependency properties. It means a service dependency property won't override a component service
* property having the same name.
*
* @param propagate true if the dependency service properties should be propagated to the component service properties.
*/
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);
/**
* Enabled debug logging for this dependency instance. The logging is prefixed with the given identifier.
* @param debugKey a prefix log identifier
* @return this service dependency.
*/
public ServiceDependency setDebug(String debugKey);
/**
* Configures whether or not this dependency should internally obtain the service object for all tracked service references.
*
* By default, DM internally dereferences all discovered service references (using
* <code>BundleContext.getService(ServiceReference ref)</code> methods.
* However, sometimes, your callback only needs the ServiceReference, and sometimes you don't want to dereference the service.
* So, in this case you can use the <code>setDereference(false)</code> method in order to tell to DM
* that it should never internally dereference the service dependency internally.
*
* @return false if the service must never be dereferenced by dependency manager (internally).
*/
public ServiceDependency setDereference(boolean dereferenceServiceInternally);
}