javadoc
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1067888 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AdapterService.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AdapterService.java
index d21f627..26507d5 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AdapterService.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AdapterService.java
@@ -24,11 +24,13 @@
import java.lang.annotation.Target;
/**
- * Annotates an Adapater Service. The adapter will be applied to any service that
- * matches the implemented interface and filter. 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.
+ * Annotates an Adapater service. Adapters, like {@link AspectService}, are used to "extend"
+ * existing services, and can publish different services based on the existing one.
+ * An example would be implementing a management interface for an existing service, etc ....
+ * <p>When you annotate an adapter class with the <code>@AdapterService</code> annotation, it will be applied
+ * to any service that matches the implemented interface and filter. The adapter will be registered
+ * with the specified interface and existing properties from the original service plus any extra
+ * properties you supply here. If you declare the original service as a member it will be injected.
*
* <h3>Usage Examples</h3>
*
@@ -39,15 +41,12 @@
* <blockquote>
* <pre>
*
- * @AdapterService(adapteeService = AdapteeService.class,
- * properties={@Property(name="param", value="value")})
- * class AdapterImpl implements AdapterService
- * {
+ * @AdapterService(adapteeService = AdapteeService.class, properties={@Property(name="param", value="value")})
+ * class AdapterImpl implements AdapterService {
* // The service we are adapting (injected by reflection)
* protected AdapteeService adaptee;
*
- * public void doWork()
- * {
+ * public void doWork() {
* adaptee.mehod1();
* adaptee.method2();
* }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AspectService.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AspectService.java
index 55c6600..fcffe88 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AspectService.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AspectService.java
@@ -24,11 +24,13 @@
import java.lang.annotation.Target;
/**
- * Annotates an Aspect Service. The aspect will be applied to any service that
- * matches the specified interface and filter. The aspect will be registered
- * with the same interface and properties as the original service, plus any
+ * Annotates an Aspect service. Aspects allow you to define an interceptor, or chain of interceptors
+ * for a service (to add features like caching or logging, etc ...). The dependency manager intercepts
+ * the original service, and allows you to execute some code before invoking the original service ...
+ * The aspect will be applied to any service that matches the specified interface and filter and
+ * 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 can declare the original service as a member it will be injected.<p>
+ * and if you declare the original service as a member it will be injected.<p>
*
* <h3>Usage Examples</h3>
*
@@ -40,15 +42,12 @@
* <blockquote>
* <pre>
*
- * @AspectService(ranking=10),
- * properties={@Property(name="param", value="value")})
- * class AspectService implements InterceptedService
- * {
+ * @AspectService(ranking=10), properties={@Property(name="param", value="value")})
+ * class AspectService implements InterceptedService {
* // The service we are intercepting (injected by reflection)
* protected InterceptedService intercepted;
*
- * public void doWork()
- * {
+ * public void doWork() {
* intercepted.doWork();
* }
* }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/BundleAdapterService.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/BundleAdapterService.java
index 04e2d47..9d5855e 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/BundleAdapterService.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/BundleAdapterService.java
@@ -26,13 +26,36 @@
import org.osgi.framework.Bundle;
/**
- * Annotates a Bundle Adapter Service class. 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 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
- * bundle as a member it will be injected.
+ * Annotates a bundle adapter service class. Bundle adapters are similar to {@link AdapterService},
+ * but instead of adapting a service, they adapt a bundle with a certain set of states (STARTED|INSTALLED|...),
+ * and provide a service on top of it. <p>
+ * The bundle adapter will be applied to any bundle that matches the specified bundle state mask and
+ * filter conditions, which may match some of the bundle OSGi manifest headers. For each matching
+ * bundle an adapter will be created based on the adapter implementation class. The adapter will be
+ * registered with the specified interface and with service properties found from the original bundle
+ * OSGi manifest headers plus any extra properties you supply here.
+ * If you declare the original bundle as a member it will be injected.
+ *
+ * <h3>Usage Examples</h3>
+ *
+ * <p> In the following example, a "VideoPlayer" Service is registered into the OSGi registry each time
+ * an active bundle containing a "Video-Path" manifest header is detected:
+ * <p>
+ * <blockquote>
+ * <pre>
+ * @BundleAdapterService(filter = "(Video-Path=*)", stateMask = Bundle.ACTIVE, propagate=true)
+ * public class VideoPlayerImpl implements VideoPlayer {
+ * Bundle bundle; // Injected by reflection
+ *
+ * void play() {
+ * URL mpegFile = bundle.getEntry(bundle.getHeaders().get("Video-Path"));
+ * // play the video provided by the bundle ...
+ * }
+ *
+ * void stop() {}
+ * }
+ * </pre>
+ * </blockquote>
*/
public @Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/BundleDependency.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/BundleDependency.java
index 80dd095..b134b44 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/BundleDependency.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/BundleDependency.java
@@ -26,7 +26,36 @@
import org.osgi.framework.Bundle;
/**
- * Annotates a method for a bundle dependency.
+ * Annotates a class or method for a bundle dependency. A bundle dependency allows you to
+ * depend on a bundle in a certain set of states (INSTALLED|RESOLVED|STARTED|...), as
+ * indicated by a state mask. You can also use a filter condition that is matched against
+ * all manifest entries. When applied on a class field, optional unavailable dependencies
+ * are injected with a NullObject.
+ *
+ * <h3>Usage Examples</h3>
+ *
+ * <p> In the following example, the "SCR" Component allows to track
+ * all bundles containing a specific "Service-Component" OSGi header, in order to load
+ * and manage all Declarative Service components specified in the SCR xml documents referenced by the header:
+ * <p>
+ * <blockquote>
+ * <pre>
+ * @Component
+ * public class SCR {
+ * @BundleDependency(required = false,
+ * removed = "unloadServiceComponents",
+ * filter = "(Service-Component=*)")
+ * void loadServiceComponents(Bundle b) {
+ * String descriptorPaths = (String) b.getHeaders().get("Service-Component");
+ * // load all service component specified in the XML descriptorPaths files ...
+ * }
+ *
+ * void unloadServiceComponents(Bundle b) {
+ * // unload all service component we loaded from our "loadServiceComponents" method.
+ * }
+ * }
+ * </pre>
+ * </blockquote>
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Composition.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Composition.java
index 7996920..0516896 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Composition.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Composition.java
@@ -24,10 +24,16 @@
import java.lang.annotation.Target;
/**
- * Annotates a method returning the list of objects which are part of the Service implementation.
- * Each instances will be injected with Service dependencies (attributes or callbacks), and if the
- * service has some annotated lifecycle callbacks (@Init/@Start/@Stop/@Destroy), then the same callbacks
- * will be invoked on the objects which are part of the composition.<p>
+ * Annotates a method returning the list of objects which are part of a Component implementation.
+ * When implementing complex Components, you often need to use more than one object instances.
+ * Moreover, several of these instances might want to have dependencies injected, as was as lifecycle
+ * callbacks invoked, like the methods annotated with {@link Init}, {@link Start}, {@link Stop},
+ * {@link Destroy} annotations. In such cases you can tell the dependency manager which instances to
+ * consider, by annotating a method in your Component, returning a list of objects which are part
+ * of the implementation.
+ * <p>
+ * This annotation may be applied on a method which is part of class annotated with either a {@link Component},
+ * {@link AspectService}, {@link AdapterService}, or {@link ResourceAdapterService} annotation.
*
* <h3>Usage Examples</h3>
*
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ConfigurationDependency.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ConfigurationDependency.java
index 5534b9f..056ad3a 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ConfigurationDependency.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ConfigurationDependency.java
@@ -25,7 +25,66 @@
/**
- * Annotates a method for injecting a Configuration Dependency.
+ * Annotates a method for injecting a Configuration Dependency. A configuration dependency
+ * is always required, and allows you to depend on the availability of a valid configuration
+ * for your component. This dependency requires the OSGi Configuration Admin Service.
+ *
+ * <h3>Usage Examples</h3>
+ *
+ * <p> In the following example, the "Printer" component depends on a configuration
+ * whose PID name is "org.apache.felix.sample.Printer". This service will initialize
+ * its ip/port number from the provided configuration:
+ * <p>
+ * <blockquote>
+ * <pre>
+ * package org.apache.felix.sample;
+ *
+ * @Component
+ * public class Printer {
+ * @ConfigurationDependency
+ * void updated(Dictionary config) {
+ * // load printer ip/port from the provided dictionary.
+ * }
+ * }
+ * </pre>
+ * </blockquote>
+ *
+ * <p> This other example shows how to specify a configuration dependency, as well as meta data
+ * used to customize the WebConsole GUI. Using these meta data, you can specify for example the
+ * default value for your configurations data, some descriptions, the cardinality of configuration
+ * values, etc ...
+ * <p>
+ * <blockquote>
+ * <pre>
+ * package org.apache.felix.sample;
+ *
+ * @Component
+ * public class Printer {
+ * @ConfigurationDependency(
+ * heading = "Printer Service",
+ * description = "Declare here parameters used to configure the Printer service",
+ * metadata = {
+ * @PropertyMetaData(heading = "Ip Address",
+ * description = "Enter the ip address for the Printer service",
+ * defaults = { "127.0.0.1" },
+ * type = String.class,
+ * id = "IPADDR",
+ * cardinality = 0),
+ * @PropertyMetaData(heading = "Port Number",
+ * description = "Enter the port number for the Printer service",
+ * defaults = { "4444" },
+ * type = Integer.class,
+ * id = "PORTNUM",
+ * cardinality = 0)
+
+ * }
+ * )
+ * void updated(Dictionary config) {
+ * // load configuration from the provided dictionary.
+ * }
+ * }
+ * </pre>
+ * </blockquote>
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Destroy.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Destroy.java
index c3ac138..5e22105 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Destroy.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Destroy.java
@@ -24,8 +24,25 @@
import java.lang.annotation.Target;
/**
- * Annotates a method which is invoked when the Service is destroyed.
- * If you don't supply this annotation, then no "destroy" method will be invoked.
+ * Annotates a method which is invoked when the component is destroyed.
+ * The method is called when the component's bundle is stopped, or when one of its
+ * required dependency is lost (unless the dependency has been defined as an "instance bound"
+ * dependency using the Dependency Manager API).
+ * </ul>
+ *
+ * <h3>Usage Examples</h3>
+ * <blockquote>
+ * <pre>
+ * @Component
+ * class MyComponent {
+ * @ServiceDependency
+ * private LogService logService; // Required dependency over the log service.
+ *
+ * @Destroy
+ * void destroyed() {} // called if bundle is stopped or if we have lost some required dependencies.
+ * }
+ * </pre>
+ * </blockquote>
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java
index fd0bee5..59e1d2c 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java
@@ -29,7 +29,114 @@
* the specified factoryPid, an instance of this service will be created.
* 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.
+ * (which don't start with ".") will be propagated along with the adapter service properties. <p>
+ *
+ * Like in @{@link ConfigurationDependency}, you can optionally specify the meta types of your
+ * configurations for Web Console GUI customization (configuration heading/descriptions/default values/etc ...).
+ *
+ * <h3>Usage Examples</h3>
+ * Here, a "Dictionary" service instance is instantiated for each existing factory configuration
+ * instances matching the factory pid "DictionaryServiceFactory".
+ * <blockquote>
+ * <pre>
+ * @FactoryConfigurationAdapterService(factoryPid="DictionaryServiceFactory", updated="updated")
+ * public class DictionaryImpl implements DictionaryService
+ * {
+ * /**
+ * * The key of our config admin dictionary language.
+ * */
+ * final static String LANG = "lang";
+ *
+ * /**
+ * * The key of our config admin dictionary values.
+ * */
+ * final static String WORDS = "words";
+ *
+ * /**
+ * * We store all configured words in a thread-safe data structure, because ConfigAdmin
+ * * may invoke our updated method at any time.
+ * */
+ * private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
+ *
+ * /**
+ * * Our Dictionary language.
+ * */
+ * private String m_lang;
+ *
+ * protected void updated(Dictionary<String, ?> config) {
+ * m_lang = (String) config.get(LANG);
+ * m_words.clear();
+ * String[] words = (String[]) config.get(WORDS);
+ * for (String word : words) {
+ * m_words.add(word);
+ * }
+ * }
+ * ...
+ * }
+ * </pre>
+ * </blockquote>
+ * Here, this is the same example as above, but using meta types:
+ *
+ * <blockquote>
+ * <pre>
+ * @FactoryConfigurationAdapterService(
+ * factoryPid="DictionaryServiceFactory",
+ * propagate=true,
+ * updated="updated",
+ * heading="Dictionary Services",
+ * description="Declare here some Dictionary instances, allowing to instantiates some DictionaryService services for a given dictionary language",
+ * metadata={
+ * @PropertyMetaData(
+ * heading="Dictionary Language",
+ * description="Declare here the language supported by this dictionary. " +
+ * "This property will be propagated with the Dictionary Service properties.",
+ * defaults={"en"},
+ * id=DictionaryImpl.LANG,
+ * cardinality=0),
+ * @PropertyMetaData(
+ * heading="Dictionary words",
+ * description="Declare here the list of words supported by this dictionary. This properties starts with a Dot and won't be propagated with Dictionary OSGi service properties.",
+ * defaults={"hello", "world"},
+ * id=DictionaryImpl.WORDS,
+ * cardinality=Integer.MAX_VALUE)
+ * }
+ * )
+ * public class DictionaryImpl implements DictionaryService
+ * {
+ * /**
+ * * The key of our config admin dictionary language.
+ * */
+ * final static String LANG = "lang";
+ *
+ * /**
+ * * The key of our config admin dictionary values.
+ * */
+ * final static String WORDS = "words";
+ *
+ * /**
+ * * We store all configured words in a thread-safe data structure, because ConfigAdmin
+ * * may invoke our updated method at any time.
+ * */
+ * private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>();
+ *
+ * /**
+ * * Our Dictionary language.
+ * */
+ * private String m_lang;
+ *
+ * protected void updated(Dictionary<String, ?> config) {
+ * m_lang = (String) config.get(LANG);
+ * m_words.clear();
+ * String[] words = (String[]) config.get(WORDS);
+ * for (String word : words) {
+ * m_words.add(word);
+ * }
+ * }
+ *
+ * ...
+ * }
+ * </pre>
+ * </blockquote>
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Init.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Init.java
index f4e3054..fbe4c58 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Init.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Init.java
@@ -25,7 +25,35 @@
/**
* Annotates a method which will be invoked when the Service is initializing.
- * If you don't supply this annotation, then no "init" method will be invoked.
+ * All required dependencies are already injected before the annotated method is called, and
+ * optional dependencies on class fields are injected with NullObjects if the optional
+ * dependencies are not currently available.<p>
+ *
+ * If some dependencies are declared using a <b>named</b> @{@link ServiceDependency} annotation,
+ * then the annotated method may optionally return a Map used to dynamically configure such
+ * dependencies (Please refer to @{@link ServiceDependency#name()} attribute for more
+ * information about this feature).<p>
+ *
+ * After the init method returns, the component is then invoked in the method annotated with
+ * @{@link Start}, in order to notify that the component is about to be registered into the OSGi
+ * registry (if this one provides a service). However, you can take control of when the service is registered,
+ * using the @{@link LifecycleController} annotation).
+ *
+ * <h3>Usage Examples</h3>
+ * Here, the "VideoPlayer" init method is called after the "log" dependency is injected.
+ * <blockquote>
+ * <pre>
+ *
+ * @Component
+ * public class VideoPlayer {
+ * @ServiceDependency
+ * LogService log;
+ *
+ * @Init
+ * void init() {} // initialize our service (the "log" dependency is already injected).
+ * }
+ * </pre>
+ * </blockquote>
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/LifecycleController.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/LifecycleController.java
index 84180c7..4cb2605 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/LifecycleController.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/LifecycleController.java
@@ -28,7 +28,7 @@
* By default, a Service is implicitly started when the service's bundle is started and when
* all required dependencies are satisfied. However, it is sometimes required to programatically
* take control of when the service is started or stopped. In this case, the injected <code>Runnable</code>
- * can be invoked in order to start (and eventually register) a Service at any time. When this annotation
+ * can be invoked in order to start/register (or stop/unregister) a Service at any time. When this annotation
* is used, then the Service on which this annotation is applied is not activated by default, and you have to
* call the injected Runnable yourself.
* <p>
@@ -42,7 +42,10 @@
* @Service
* class X implements Z {
* @LifecycleController
- * Runnable m_starter
+ * Runnable starter
+ *
+ * @LifecycleController(start=false)
+ * Runnable stopper
*
* @Init
* void init() {
@@ -50,7 +53,12 @@
* Thread t = new Thread() {
* public void run() {
* sleep(2000);
- * m_starter.run();
+ * // start our "Z" service (our "start" method will be called, juste before service registration
+ * starter.run();
+ *
+ * sleep(2000);
+ * // now, stop/unregister the "Z" service (we'll then be called in our stop() method
+ * stopper.run();
* }
* };
* t.start();
@@ -58,9 +66,16 @@
*
* @Start
* public void start() {
- * // This method will be called after we invoke our m_starter Runnable, and our service will be
+ * // This method will be called after we invoke our starter Runnable, and our service will be
* // published after our method returns, as in normal case.
* }
+
+ * @Stop
+ * public void stop() {
+ * // This method will be called after we invoke our "stop" Runnable, and our service will be
+ * // unregistered after our method returns, as in normal case. Notice that the service won't
+ * // be destroyed here, and the "starter" runnable can be re-invoked later.
+ * }
* }
* </pre>
* </blockquote>
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/PropertyMetaData.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/PropertyMetaData.java
index bdf647d..ad3e4ab 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/PropertyMetaData.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/PropertyMetaData.java
@@ -27,7 +27,7 @@
/**
* This annotation describes the data types of a configuration Property.
* It can be used by other annotations which require meta type support.
- * For now, the following annotations are using <code>PropertyMeteData</code:
+ * For now, the following annotations are using <code>PropertyMetaData</code:
* <ul>
* <li>{@link ConfigurationDependency}: This dependency allows to define a
* dependency over a <code>Configuration Admin</code> configuration dictionaries, whose
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceAdapterService.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceAdapterService.java
index 287eb48..486a0a0 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceAdapterService.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceAdapterService.java
@@ -23,15 +23,102 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-
/**
- * Annotates a class as a Resource Adapter Service. 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.
+ * Annotates a class as a Resource adapter service. Resource adapters are things that
+ * adapt a resource instead of a service, and provide an adapter service on top of this resource.
+ * Resources are an abstraction that is introduced by the dependency manager, represented as a URL.
+ * They can be implemented to serve resources embedded in bundles, somewhere on a file system or in
+ * an http content repository server, or database.<p>
+ * The adapter will be applied to any resource that matches the specified filter condition, which can
+ * match some part of the resource URL (with "path", "protocol", "port", or "host" filters).
+ * 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 with any extra service properties
+ * you supply here. Moreover, the following service properties will be propagated from the resource URL:
+ *
+ * <ul><li> "host": this property exposes the host part of the resource URL
+ * <li>"path": the resource URL path
+ * <li>"protocol": the resource URL protocol
+ * <li>"port": the resource URL port
+ * </ul>
+ *
+ * <h3>Usage Examples</h3>
+ * Here, the "VideoPlayer" service provides a video service on top of any movie resources, with service
+ * properties "host"/"port"/"protocol"/"path" extracted from the resource URL:
+ * <blockquote>
+ * <pre>
+ *
+ * @ResourceAdapterService(filter = "(&(path=/videos/*.mkv)(host=localhost))", propagate = true)
+ * public class VideoPlayerImpl implements VideoPlayer {
+ * // Injected by reflection
+ * URL resource;
+ *
+ * void play() {} // play video referenced by this.resource
+ * void stop() {} // stop playing the video
+ * void transcode() {} // ...
+ * }
+ * </pre>
+ * </blockquote>
+ *
+ * And here is an example of a VideoProvider, which provides some videos using a web URL.
+ * Notice that Resource providers need to depend on the DependencyManager API:
+ *
+ * <blockquote>
+ * <pre>
+ * import java.net.MalformedURLException;
+ * import java.net.URL;
+ * import java.util.HashMap;
+ * import java.util.Map;
+ *
+ * import org.apache.felix.dm.ResourceHandler;
+ * import org.apache.felix.dm.ResourceUtil;
+ * import org.apache.felix.dm.annotation.api.Component;
+ * import org.apache.felix.dm.annotation.api.Init;
+ * import org.apache.felix.dm.annotation.api.ServiceDependency;
+ * import org.osgi.framework.BundleContext;
+ * import org.osgi.framework.Filter;
+ * import org.osgi.framework.InvalidSyntaxException;
+ *
+ * @Component
+ * public class VideoProvider
+ * {
+ * // Injected by reflection
+ * private volatile BundleContext context;
+ * // List of known resource handlers
+ * private Map<ResourceHandler, Filter> m_handlers = new HashMap<ResourceHandler, Filter>();
+ * // List of known video resources
+ * private URL[] m_videos;
+ *
+ * @Init
+ * void init() throws MalformedURLException
+ * {
+ * m_videos = new URL[] {
+ * new URL("http://localhost:8080/videos/video1.mkv"),
+ * new URL("http://localhost:8080/videos/video2.mkv"),
+ * };
+ * }
+ *
+ * // Track resource handlers
+ * @ServiceDependency(required = false)
+ * public void add(Map<String, String> serviceProperties, ResourceHandler handler) throws InvalidSyntaxException
+ * {
+ * String filterString = serviceProperties.get("filter");
+ * filterString = (filterString != null) ? filterString : "(path=*)";
+ * Filter filter = context.createFilter(filterString);
+ * synchronized (this)
+ * {
+ * m_handlers.put(handler, filter);
+ * }
+ * for (URL video : m_videos)
+ * {
+ * if (filter.match(ResourceUtil.createProperties(video)))
+ * {
+ * handler.added(video);
+ * }
+ * }
+ * }
+ * }
+ * </pre>
+ * </blockquote>
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
@@ -53,7 +140,7 @@
String filter();
/**
- * <code>true</code> if properties from the resource should be propagated to the service.
+ * <code>true</code> if properties from the resource should be propagated to the service properties.
*/
boolean propagate() default false;
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceDependency.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceDependency.java
index 43abe42..781794e 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceDependency.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceDependency.java
@@ -24,7 +24,85 @@
import java.lang.annotation.Target;
/**
- * Annotates a method of field as a Resource Dependency.
+ * Annotates a method of field as a Resource Dependency. A resource dependency allows you to
+ * depend on a resource. Resources are an abstraction that is introduced by the dependency manager, represented as a URL.
+ * They can be implemented to serve resources embedded in bundles, somewhere on a file system or in
+ * an http content repository server, or database. <p> A resource is a URL and you can use a filter condition based on
+ * protocol, host, port, and path.
+ *
+ * <h3>Usage Examples</h3>
+ * Here, the "VideoPlayer" component plays any provided MKV video resources
+ * <blockquote>
+ * <pre>
+ *
+ * @Component
+ * public class VideoPlayer {
+ * @ResourceDependency(required=false, filter="(path=/videos/*.mkv)")
+ * void playResource(URL video) { ... }
+ * }
+ * </pre>
+ * </blockquote>
+ *
+ * And here is an example of a VideoProvider, which provides some videos using a web URL.
+ * Notice that Resource providers need to depend on the DependencyManager API:
+ *
+ * <blockquote>
+ * <pre>
+ * import java.net.MalformedURLException;
+ * import java.net.URL;
+ * import java.util.HashMap;
+ * import java.util.Map;
+ *
+ * import org.apache.felix.dm.ResourceHandler;
+ * import org.apache.felix.dm.ResourceUtil;
+ * import org.apache.felix.dm.annotation.api.Component;
+ * import org.apache.felix.dm.annotation.api.Init;
+ * import org.apache.felix.dm.annotation.api.ServiceDependency;
+ * import org.osgi.framework.BundleContext;
+ * import org.osgi.framework.Filter;
+ * import org.osgi.framework.InvalidSyntaxException;
+ *
+ * @Component
+ * public class VideoProvider
+ * {
+ * // Injected by reflection
+ * private volatile BundleContext context;
+ * // List of known resource handlers
+ * private Map<ResourceHandler, Filter> m_handlers = new HashMap<ResourceHandler, Filter>();
+ * // List of known video resources
+ * private URL[] m_videos;
+ *
+ * @Init
+ * void init() throws MalformedURLException
+ * {
+ * m_videos = new URL[] {
+ * new URL("http://localhost:8080/videos/video1.mkv"),
+ * new URL("http://localhost:8080/videos/video2.mkv"),
+ * };
+ * }
+ *
+ * // Track resource handlers
+ * @ServiceDependency(required = false)
+ * public void add(Map<String, String> serviceProperties, ResourceHandler handler) throws InvalidSyntaxException
+ * {
+ * String filterString = serviceProperties.get("filter");
+ * filterString = (filterString != null) ? filterString : "(path=*)";
+ * Filter filter = context.createFilter(filterString);
+ * synchronized (this)
+ * {
+ * m_handlers.put(handler, filter);
+ * }
+ * for (URL video : m_videos)
+ * {
+ * if (filter.match(ResourceUtil.createProperties(video)))
+ * {
+ * handler.added(video);
+ * }
+ * }
+ * }
+ * }
+ * </pre>
+ * </blockquote>
*/
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD})
@@ -48,20 +126,18 @@
/**
* Returns whether the Service dependency is required or not.
- * @return true if the dependency is required, false if not.
*/
boolean required() default true;
/**
* Returns the Service dependency OSGi filter.
- * @return The Service dependency filter.
*/
String filter() default "";
/**
- * TODO add comments for this method.
- * @param propagate
- * @return
+ * Specifies if the resource URL properties must be propagated. If set to true, then the URL properties
+ * ("protocol"/"host"/"port"/"path") will be propagated to the service properties of the component which
+ * is using this dependency.
*/
boolean propagate() default false;
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ServiceDependency.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ServiceDependency.java
index 14da19e..30a06e6 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ServiceDependency.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ServiceDependency.java
@@ -26,6 +26,16 @@
/**
* Annotates a method or a field for injecting a Service Dependency. When applied on a class
* field, optional unavailable dependencies are injected with a NullObject.
+ *
+ * <h3>Usage Examples</h3>
+ * Here, the MyComponent component is injected with a dependency over a "MyDependency" service
+ *
+ * <blockquote><pre>
+ * @Component
+ * class MyComponent {
+ * @ServiceDependency(timeout=15000)
+ * MyDependency dependency;
+ * </pre></blockquote>
*/
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD})
@@ -85,10 +95,10 @@
*
* <p> Sample Code:<p>
* <blockquote><pre>
- * @Service
+ * @Component
* class MyServer implements Runnable {
* @ServiceDependency(timeout=15000)
- * MyDependency _dependency;.
+ * MyDependency dependency;.
*
* @Start
* void start() {
@@ -97,7 +107,7 @@
*
* public void run() {
* try {
- * _dependency.doWork();
+ * dependency.doWork();
* } catch (IllegalStateException e) {
* t.printStackTrace();
* }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Start.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Start.java
index 60af798..09d61af 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Start.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Start.java
@@ -24,18 +24,18 @@
import java.lang.annotation.Target;
/**
- * Annotates a method which will be invoked when the Service is started.
- * The annotated method will be called when all required dependencies have been injected, and
- * just before registering the service into the OSGi registry (if the service provides an interface).
- * Notice that the start method may optionally return a Map which will be propagated to the provided
- * service properties.
+ * Annotates a method which will be invoked when the component is started.
+ * The annotated method is invoked juste before registering the service into the OSGi registry
+ * (if the service provides an interface). Notice that the start method may optionally return
+ * a Map which will be propagated to the provided service properties.<p>
+ * Service activation/deactivation can be programatically controlled using {@link LifecycleController}.
*
* <p>
* <h3>Usage Examples</h3>
* <blockquote>
*
* <pre>
- * @Service(properties={@Property(name="foo", value="bar")})
+ * @Component(properties={@Property(name="foo", value="bar")})
* class X implements Z {
* @ServiceDependency
* OtherService m_dependency;
@@ -44,7 +44,7 @@
* Map start() {
* // Our Z Service is ready (all required dependencies have been satisfied), and is about to be
* // registered into the OSGi registry. We return here an optional Map containing some extra-properties
- * // which will be appended to the properties supplied in the Service annotation.
+ * // which will be appended to the properties supplied in the Component annotation.
* return new HashMap() {{ put("foo2", "bar2"); }};
* }
* }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Stop.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Stop.java
index 3d5ec17..038c7a5 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Stop.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Stop.java
@@ -24,8 +24,26 @@
import java.lang.annotation.Target;
/**
- * Annotates a method which is invoked when the Service is stopped.
- * If you don't supply this annotation, then no "stop" method will be invoked.
+ * Annotates a method which is invoked when the Service is being unregistered from the
+ * OSGi registry.
+ * The method is called when the component's bundle is stopped, or when one of its
+ * required dependency is lost, or when a {@link LifecycleController} is programatically used to
+ * stop a service.
+ * </ul>
+ *
+ * <h3>Usage Examples</h3>
+ * <blockquote>
+ * <pre>
+ * @Component
+ * class MyComponent implements MyService {
+ * @ServiceDependency
+ * private LogService logService; // Required dependency over the log service.
+ *
+ * @Stop
+ * void stop() {} // We are unregistering from the OSGi registry.
+ * }
+ * </pre>
+ * </blockquote>
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)