FELIX-5180: Support for Java8 Repeatable Properties in DM annotations. Also, fixed some javadoc issues.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1728893 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/AdapterService.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/AdapterService.java
index bf64c19..209a442 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/AdapterService.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/AdapterService.java
@@ -37,11 +37,12 @@
* <p> Here, the AdapterService is registered into the OSGI registry each time an AdapteeService
* is found from the registry. The AdapterImpl class adapts the AdapteeService to the AdapterService.
* The AdapterService will also have a service property (param=value), and will also include eventual
- * service properties found from the AdapteeService:<p>
+ * service properties found from the AdapteeService:
* <blockquote>
* <pre>
*
- * @AdapterService(adapteeService = AdapteeService.class, properties={@Property(name="param", value="value")})
+ * @AdapterService(adapteeService = AdapteeService.class)
+ * @Property(name="param", value="value")
* class AdapterImpl implements AdapterService {
* // The service we are adapting (injected by reflection)
* protected AdapteeService adaptee;
@@ -62,62 +63,73 @@
{
/**
* Sets the adapter service interface(s). By default, the directly implemented interface(s) is (are) used.
+ * @return the adapter service interface(s)
*/
Class<?>[] provides() default {};
/**
* Sets some additional properties to use with the adapter service registration. By default,
* the adapter will inherit all adaptee service properties.
+ * @return some additional properties
*/
Property[] properties() default {};
/**
* Sets the adaptee service interface this adapter is applying to.
+ * @return the adaptee service interface this adapter is applying to.
*/
Class<?> adapteeService();
/**
* Sets the filter condition to use with the adapted service interface.
+ * @return the adaptee filter
*/
String adapteeFilter() default "";
/**
* Sets the static method used to create the adapter service implementation instance.
* By default, the default constructor of the annotated class is used.
+ * @return the factory method
*/
String factoryMethod() default "";
/**
* Sets the field name where to inject the original service. By default, the original service is injected
* in any attributes in the aspect implementation that are of the same type as the aspect interface.
+ * @return the field used to inject the original service
*/
String field() default "";
/**
* The callback method to be invoked when the original service is available. This attribute can't be mixed with
* the field attribute.
+ * @return the add callback
*/
String added() default "";
/**
* The callback method to be invoked when the original service properties have changed. When this attribute is used,
* then the added attribute must also be used.
+ * @return the changed callback
*/
String changed() default "";
/**
* name of the callback method to invoke on swap.
+ * @return the swap callback
*/
String swap() default "";
/**
* The callback method to invoke when the service is lost. When this attribute is used, then the added attribute
* must also be used.
+ * @return the remove callback
*/
String removed() default "";
/**
* Specifies if adaptee service properties should be propagated to the adapter service.
+ * @return the service propagation flag
*/
boolean propagate() default true;
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/AspectService.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/AspectService.java
index 600ba85..9a3961a 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/AspectService.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/AspectService.java
@@ -30,7 +30,7 @@
* 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 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.
*
* <h3>Usage Examples</h3>
*
@@ -38,11 +38,12 @@
* is found from the registry. The AspectService class intercepts the InterceptedService, and decorates
* its "doWork()" method. This aspect uses a rank with value "10", meaning that it will intercept some
* other eventual aspects with lower ranks. The Aspect also uses a service property (param=value), and
- * include eventual service properties found from the InterceptedService:<p>
+ * include eventual service properties found from the InterceptedService:
* <blockquote>
* <pre>
*
- * @AspectService(ranking=10), properties={@Property(name="param", value="value")})
+ * @AspectService(ranking=10))
+ * @Property(name="param", value="value")
* class AspectService implements InterceptedService {
* // The service we are intercepting (injected by reflection)
* protected InterceptedService intercepted;
@@ -62,52 +63,60 @@
{
/**
* Sets the service interface to apply the aspect to. By default, the directly implemented interface is used.
+ * @return the service aspect
*/
Class<?> service() default Object.class;
/**
* Sets the filter condition to use with the service interface this aspect is applying to.
+ * @return the service aspect filter
*/
String filter() default "";
/**
* Sets Additional properties to use with the aspect service registration
+ * @return the aspect service properties.
*/
Property[] properties() default {};
/**
* Sets the ranking of this aspect. Since aspects are chained, the ranking defines the order in which they are chained.
- * Chain ranking is implemented as a service ranking so service lookups automatically retrieve the top of the
- * chain.
+ * Chain ranking is implemented as a service ranking so service lookups automatically retrieve the top of the chain.
+ * @return the aspect service rank
*/
int ranking();
/**
* Sets the field name where to inject the original service. By default, the original service is injected
* in any attributes in the aspect implementation that are of the same type as the aspect interface.
+ * @return the field used to inject the original service
*/
String field() default "";
/**
* The callback method to be invoked when the original service is available. This attribute can't be mixed with
* the field attribute.
+ * @return the add callback
*/
String added() default "";
/**
* The callback method to be invoked when the original service properties have changed. When this attribute is used,
* then the added attribute must also be used.
+ * @return the changed callback
*/
String changed() default "";
/**
* The callback method to invoke when the service is lost. When this attribute is used, then the added attribute
* must also be used.
+ * @return the remove callback
*/
String removed() default "";
/**
* name of the callback method to invoke on swap.
+ * @return the swap callback
*/
String swap() default "";
@@ -115,6 +124,7 @@
* Sets the static method used to create the AspectService implementation instance. The
* default constructor of the annotated class is used. The factoryMethod can be used to provide a specific
* aspect implements, like a DynamicProxy.
+ * @return the aspect service factory method
*/
String factoryMethod() default "";
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/BundleAdapterService.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/BundleAdapterService.java
index 7c0d5e9..c559e40 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/BundleAdapterService.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/BundleAdapterService.java
@@ -40,7 +40,7 @@
*
* <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)
@@ -66,31 +66,37 @@
/**
* The interface(s) to use when registering adapters. By default, the interface(s) directly implemented
* by the annotated class is (are) used.
+ * @return the interface(s) to use when registering adapters
*/
Class<?>[] provides() default {};
/**
* Additional properties to use with the service registration
+ * @return the bundle adapter properties
*/
Property[] properties() default {};
/**
* The filter used to match a given bundle.
+ * @return the bundle adapter filter
*/
String filter();
/**
* the bundle state mask to apply
+ * @return the bundle state mask to apply
*/
int stateMask() default Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE;
/**
* Specifies if manifest headers from the bundle should be propagated to the service properties.
+ * @return the propagation flag
*/
boolean propagate() default true;
/**
* Sets the static method used to create the BundleAdapterService implementation instance.
+ * @return the factory method
*/
String factoryMethod() default "";
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/BundleDependency.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/BundleDependency.java
index 2c0adaf..273f9bc 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/BundleDependency.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/BundleDependency.java
@@ -37,7 +37,7 @@
* <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
@@ -66,32 +66,38 @@
{
/**
* Returns the callback method to be invoked when the service have changed.
+ * @return the change callback
*/
String changed() default "";
/**
* Returns the callback method to invoke when the service is lost.
+ * @return the remove callback
*/
String removed() default "";
/**
* Returns whether the dependency is required or not.
+ * @return the required flag
*/
boolean required() default true;
/**
* Returns the filter dependency
+ * @return the filter
*/
String filter() default "";
/**
* Returns the bundle state mask
+ * @return the state mask
*/
int stateMask() default Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE;
/**
* Specifies if the manifest headers from the bundle should be propagated to
* the service properties.
+ * @return the propagation flag
*/
boolean propagate() default false;
@@ -104,6 +110,7 @@
* your named dependencies, which will then be calculated once the init() method returns.
*
* <p> See {@link Init} annotation for an example usage of a dependency dynamically configured from the init method.
+ * @return the dependency name used to dynamically configure the dependency from the init callback
*/
String name() default "";
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Component.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Component.java
index 0aa07ed..8f9a443 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Component.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Component.java
@@ -41,7 +41,7 @@
*
* <h3>Usage Examples</h3>
*
- * <p> Here is a sample showing a X component, which depends on a configuration dependency:<p>
+ * Here is a sample showing a X component, which depends on a configuration dependency:
* <blockquote>
*
* <pre>
@@ -69,7 +69,7 @@
* </blockquote>
*
* Here is a sample showing how a Y component may dynamically instantiate several X component instances,
- * using the {@link #factoryName()} attribute:<p>
+ * using the {@link #factoryName()} attribute:
* <blockquote>
*
* <pre>
@@ -157,11 +157,14 @@
/**
* Sets list of provided interfaces. By default, the directly implemented interfaces are provided.
+ * @return the provided interfaces
*/
Class<?>[] provides() default {};
/**
- * Sets list of provided service properties.
+ * Sets list of provided service properties. Since R7 version, Property annotation is repeatable and you can directly
+ * apply it on top of the component class multiple times, instead of using the Component properties attribute.
+ * @return the component properties.
*/
Property[] properties() default {};
@@ -186,6 +189,7 @@
* using the {@value #FACTORY_INSTANCE} key.
*
* @deprecated use {@link #factoryName()} instead of a factorySet.
+ * @return the factory set name
*/
String factorySet() default "";
@@ -204,6 +208,7 @@
*
* <p>Optionally, the dictionary registered into the factory set may provide an implementation instance for the component to be created,
* using a "dm.runtime.factory.instance" key.
+ * @return the factory name
*/
String factoryName() default "";
@@ -212,11 +217,13 @@
* {@link #factoryName()} attribute is used. If specified, then this attribute references a callback method, which is called
* for providing the configuration supplied by the factory that instantiated this component. The current component service properties will be
* also updated with all public properties (which don't start with a dot).
+ * @return the factory configure callback name
*/
String factoryConfigure() default "";
/**
* Sets the static method used to create the components implementation instance.
+ * @return the factory method used to instantiate the component
*/
String factoryMethod() default "";
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Composition.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Composition.java
index b62ac70..3ee2435 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Composition.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Composition.java
@@ -40,7 +40,7 @@
*
* <p> Here, the "MyComponent" component is composed of the Helper class, which is also injected with
* service dependencies. The lifecycle callbacks are also invoked in the Helper (if the Helper defines
- * them):<p>
+ * them):
* <blockquote>
* <pre>
*
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ConfigurationDependency.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ConfigurationDependency.java
index 30ebf46..4a09be2 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ConfigurationDependency.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ConfigurationDependency.java
@@ -91,6 +91,7 @@
* Returns the pid from a class name. The full class name will be used as the configuration PID.
* You can use this method when you use an interface annoted with standard bndtols metatype annotations.
* (see http://www.aqute.biz/Bnd/MetaType).
+ * @return the pid class
*/
Class<?> pidClass() default Object.class;
@@ -150,6 +151,7 @@
* }
* }
* </pre></blockquote>
+ * @return the dependency name used to configure the dependency dynamically from init callback
*/
String name() default "";
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Destroy.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Destroy.java
index 4934c89a..f81088a 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Destroy.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Destroy.java
@@ -28,7 +28,7 @@
* 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>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java
index 44fc281..245a12c 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java
@@ -29,7 +29,7 @@
* factory configuration matching 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. <p>
+ * (which don't start with ".") will be propagated along with the adapter service properties.
*
* <h3>Usage Examples</h3>
* Here, a "Dictionary" service instance is created for each existing "sample.DictionaryConfiguration" factory pids.
@@ -50,7 +50,7 @@
* String lang();
*
* @AD(description = "Declare here the list of words supported by this dictionary.")
- * List<String> words();
+ * List<String> words();
* }
* </pre>
* </blockquote>
@@ -88,18 +88,21 @@
/**
* The interface(s) to use when registering adapters. By default, directly implemented
* interfaces will be registered in the OSGi registry.
+ * @return the registered service interfaces
*/
Class<?>[] provides() default {};
/**
* Adapter Service properties. Notice that public factory configuration is also registered in service properties,
* (only if propagate is true). Public factory configuration properties are those which don't starts with a dot (".").
+ * @return the adapter service properties
*/
Property[] properties() default {};
/**
* Returns the factory pid whose configurations will instantiate the annotated service class. (By default, the pid is the
* service class name).
+ * @return the factory pid
*/
String factoryPid() default "";
@@ -107,11 +110,13 @@
* Returns the factory pid from a class name. The full class name will be used as the configuration PID.
* You can use this method when you use an interface annoted with standard bndtols metatype annotations.
* (see http://www.aqute.biz/Bnd/MetaType).
+ * @return the factory pid class
*/
Class<?> factoryPidClass() default Object.class;
/**
* The Update method to invoke (defaulting to "updated"), when a factory configuration is created or updated
+ * @return the updated callback
*/
String updated() default "updated";
@@ -145,6 +150,7 @@
/**
* Sets the static method used to create the adapter instance.
+ * @return the factory method
*/
String factoryMethod() default "";
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Init.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Init.java
index 0bc5448..4eb71d0 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Init.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Init.java
@@ -27,7 +27,7 @@
* Annotates a method used to configure dynamic dependencies.
* When this method is invoked, all required dependencies (except the ones declared with a <code>name</code>
* attribute) are already injected, and optional dependencies on class fields
- * are also already injected (possibly with NullObjects).<p>
+ * are also already injected (possibly with NullObjects).
*
* The purpose of the @Init method is to either declare more dynamic dependencies using the DM API, or to
* return a Map used to dynamically configure dependencies that are annotated using a <code>name</code> attribute.
@@ -66,9 +66,9 @@
*
* // Dynamically configure the dependency declared with a "storage" name.
* @Init
- * Map<String, String> init() {
+ * Map<String, String> init() {
* log.log(LogService.LOG_WARNING, "init: storage type=" + storageType + ", storageRequired=" + storageRequired);
- * Map<String, String> props = new HashMap<>();
+ * Map<String, String> props = new HashMap<>();
* props.put("storage.required", Boolean.toString(_xmlConfiguration.isStorageRequired()))
* props.put("storage.filter", "(type=" + _xmlConfiguration.getStorageType() + ")");
* return props;
@@ -80,7 +80,7 @@
* log.log(LogService.LOG_WARNING, "start");
* }
*
- * @Override
+ * @Override
* void store(String key, String value) {
* storage.store(key, value);
* }
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Inject.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Inject.java
index e97c627..42e9739 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Inject.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Inject.java
@@ -33,7 +33,6 @@
* <li>Component: the component instance of the dependency manager
* </ul>
*
- * <p>
* <h3>Usage Examples</h3>
* <blockquote>
*
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/LifecycleController.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/LifecycleController.java
index afd9295..0f42364 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/LifecycleController.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/LifecycleController.java
@@ -31,15 +31,15 @@
* 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>
+ *
* <h3>Usage Examples</h3>
* <blockquote>
*
* <pre>
* /**
- * * This Service will be registered programatically into the OSGi registry, using the LifecycleController annotation.
+ * * This Service will be registered programmatically into the OSGi registry, using the LifecycleController annotation.
* */
- * @Service
+ * @Component
* class X implements Z {
* @LifecycleController
* Runnable starter
@@ -69,7 +69,7 @@
* // 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
@@ -87,9 +87,11 @@
public @interface LifecycleController
{
/**
- * Specifies the action to be performed when the Injected runnable is invoked. By default, the
+ * Specifies the action to be performed when the injected runnable is invoked. By default, the
* Runnable will fire a Service Component activation, when invoked. If you specify this attribute
* to false, then the Service Component will be stopped, when the runnable is invoked.
+ * @return true if the component must be started when you invoke the injected runnable, or false if
+ * the component must stopped when invoking the runnable.
*/
public boolean start() default true;
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Property.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Property.java
index f760ee9..9c55b88 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Property.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Property.java
@@ -19,6 +19,7 @@
package org.apache.felix.dm.annotation.api;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -28,9 +29,10 @@
* declaring {@link Component#properties()} attribute.<p>
*
* Property value(s) type is String by default, and the type is scalar if the value is single-valued,
- * or an array if the value is multi-valued.
+ * or an array if the value is multi-valued. You can apply this annotation on a component class multiple times
+ * (it's a java8 repeatable property).
*
- * Eight primitive types are supported:<p>
+ * Eight primitive types are supported:
* <ul>
* <li> String (default type)
* <li> Long
@@ -48,17 +50,15 @@
* Notice that you can also specify service properties dynamically by returning a Map from a method
* annotated with {@link Start}.
*
- * <p>
* <h3>Usage Examples</h3>
* <blockquote>
- *
* <pre>
- * @Component(properties={
- * @Property(name="p1", value="v")}) // String value type (scalar)
- * @Property(name="p2", value={"s1", "s2")}) // Array of Strings
- * @Property(name="service.ranking", intValue=10) // Integer value type (scalar)
- * @Property(name="p3", intValue={1,2}) // Array of Integers
- * @Property(name="p3", value={"1"), type=Long.class}) // Long value (scalar)
+ * @Component
+ * @Property(name="p1", value="v") // String value type (scalar)
+ * @Property(name="p2", value={"s1", "s2"}) // Array of Strings
+ * @Property(name="service.ranking", intValue=10) // Integer value type (scalar)
+ * @Property(name="p3", intValue={1,2}) // Array of Integers
+ * @Property(name="p3", value="1", type=Long.class) // Long value (scalar)
* class ServiceImpl implements Service {
* }
* </pre>
@@ -67,7 +67,8 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
@Retention(RetentionPolicy.CLASS)
-@Target( { ElementType.ANNOTATION_TYPE })
+@Target( { ElementType.TYPE, ElementType.ANNOTATION_TYPE })
+@Repeatable(RepeatableProperty.class)
public @interface Property
{
/**
@@ -96,41 +97,49 @@
/**
* A Long value or an array of Long values.
+ * @return the long value(s).
*/
long[] longValue() default {};
/**
* A Double value or an array of Double values.
+ * @return the double value(s).
*/
double[] doubleValue() default {};
/**
* A Float value or an array of Float values.
+ * @return the float value(s).
*/
float[] floatValue() default {};
/**
* An Integer value or an array of Integer values.
+ * @return the int value(s).
*/
int[] intValue() default {};
/**
* A Byte value or an array of Byte values.
+ * @return the byte value(s).
*/
byte[] byteValue() default {};
/**
* A Character value or an array of Character values.
+ * @return the char value(s).
*/
char[] charValue() default {};
/**
- * A Boolean value or an array of Boolean values.
+ * A Boolean value or an array of Boolean values.
+ * @return the boolean value(s).
*/
boolean[] booleanValue() default {};
/**
* A Short value or an array of Short values.
+ * @return the short value(s).
*/
short[] shortValue() default {};
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/PropertyMetaData.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/PropertyMetaData.java
index 8e7d724..5a701d8 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/PropertyMetaData.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/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>PropertyMetaData</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
@@ -56,7 +56,7 @@
String id();
/**
- * Return the property primitive type. If must be either one of the following types:<p>
+ * Return the property primitive type. If must be either one of the following types:
* <ul>
* <li>String.class</li>
* <li>Long.class</li>
@@ -67,15 +67,17 @@
* <li>Float.class</li>
* <li>Boolean.class</li>
* </ul>
+ * @return the property type
*/
Class<?> type() default String.class;
/**
- * Return a default for this property. The object must be of the appropriate type as defined by the cardinality and getType().
+ * Return default value(s) 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.
+ * the special case of a 0 cardinality, meaning a single value, does not allow arrays or vectors of 0 elements.
+ * @return the default values
*/
String[] defaults() default {};
@@ -88,20 +90,22 @@
/**
* 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>
+ * The return value is defined as follows:
*
* <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>
+ * <li> x lower than 0 -x = max occurrences, store in Vector</li>
+ * <li> x greater than 0 x = max occurrences, store in array []</li>
+ * <li> x equals Integer.MAX_VALUE no limit, but use array []</li>
+ * <li> x equals 0 1 occurrence required</li>
* </ul>
+ * @return the property cardinality
*/
int cardinality() default 0;
/**
* Tells if this property is required or not.
+ * @return true if the property is required, false if not
*/
boolean required() default true;
@@ -116,6 +120,7 @@
/**
* Return a list of option values that this property can take. This list must be in the same sequence as the {@link #optionLabels()}
* attribute.
+ * @return the option values
*/
String[] optionValues() default {};
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Registered.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Registered.java
index 5c34855..40d0c53 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Registered.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Registered.java
@@ -29,7 +29,6 @@
* When a service is registered, the ServiceRegistration used to register the service is
* also passed to the method (if it takes a ServiceRegistration as parameter).
*
- * <p>
* <h3>Usage Examples</h3>
* <blockquote>
*
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/RepeatableProperty.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/RepeatableProperty.java
new file mode 100644
index 0000000..53e2d93
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/RepeatableProperty.java
@@ -0,0 +1,41 @@
+/*
+ * 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.annotation.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used to describe repeated Property annotation. You actually don't have to use directly this annotation,
+ * which is used used to allow to repeat several times the {@link Property} annotation on a given component class.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target( { ElementType.TYPE, ElementType.ANNOTATION_TYPE })
+public @interface RepeatableProperty
+{
+ /**
+ * Returns the set of repeated {@link Property} applied on a given component class.
+ * @return the set of repeated {@link Property} applied on a given component class.
+ */
+ Property[] value();
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ResourceAdapterService.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ResourceAdapterService.java
index bfa388b..92d4114 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ResourceAdapterService.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ResourceAdapterService.java
@@ -47,7 +47,7 @@
* <blockquote>
* <pre>
*
- * @ResourceAdapterService(filter = "(&(path=/videos/*.mkv)(host=localhost))", propagate = true)
+ * @ResourceAdapterService(filter = "(&(path=/videos/*.mkv)(host=localhost))", propagate = true)
* public class VideoPlayerImpl implements VideoPlayer {
* // Injected by reflection
* URL resource;
@@ -128,31 +128,37 @@
{
/**
* The interface(s) to use when registering adapters
+ * @return the provided interfaces
*/
Class<?>[] provides() default {};
/**
* Additional properties to use with the adapter service registration
+ * @return the properties
*/
Property[] properties() default {};
/**
* The filter condition to use with the resource.
+ * @return the filter
*/
String filter();
/**
* <code>true</code> if properties from the resource should be propagated to the service properties.
+ * @return the propagate flag
*/
boolean propagate() default false;
/**
* The callback method to be invoked when the Resource has changed.
+ * @return the changed callback
*/
String changed() default "";
/**
* Sets the static method used to create the AdapterService implementation instance.
+ * @return the factory method
*/
String factoryMethod() default "";
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ResourceDependency.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ResourceDependency.java
index 5da30ff..b62863d 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ResourceDependency.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ResourceDependency.java
@@ -113,26 +113,31 @@
/**
* Returns the callback method to be invoked when the service is available. This attribute is only meaningful when
* the annotation is applied on a class field.
+ * @return the add callback
*/
String added() default "";
/**
* Returns the callback method to be invoked when the service properties have changed.
+ * @return the change callback
*/
String changed() default "";
/**
* Returns the callback method to invoke when the service is lost.
+ * @return the remove callback
*/
String removed() default "";
/**
* Returns whether the Service dependency is required or not.
+ * @return the required flag
*/
boolean required() default true;
/**
* Returns the Service dependency OSGi filter.
+ * @return the filter
*/
String filter() default "";
@@ -140,6 +145,7 @@
* 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.
+ * @return the propagate flag
*/
boolean propagate() default false;
@@ -152,6 +158,7 @@
* your named dependencies, which will then be calculated once the init() method returns.
*
* <p> See {@link Init} annotation for an example usage of a dependency dynamically configured from the init method.
+ * @return the dependency name
*/
String name() default "";
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ServiceDependency.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ServiceDependency.java
index 50105a1..1dcee0d 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ServiceDependency.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ServiceDependency.java
@@ -46,37 +46,44 @@
/**
* The type if the service this dependency is applying on. By default, the method parameter
* (or the class field) is used as the type.
+ * @return the service dependency
*/
Class<?> service() default Object.class;
/**
* The Service dependency OSGi filter.
+ * @return the service filter
*/
String filter() default "";
/**
* The class for the default implementation, if the dependency is not available.
+ * @return the default implementation class
*/
Class<?> defaultImpl() default Object.class;
/**
* Whether the Service dependency is required or not.
+ * @return the required flag
*/
boolean required() default true;
/**
* The callback method to be invoked when the service is available. This attribute is only meaningful when
* the annotation is applied on a class field.
+ * @return the add callback
*/
String added() default "";
/**
* The callback method to be invoked when the service properties have changed.
+ * @return the change callback
*/
String changed() default "";
/**
* The callback method to invoke when the service is lost.
+ * @return the remove callback
*/
String removed() default "";
@@ -89,13 +96,12 @@
* 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>
- * Notice that the changed/removed callbacks are not used when the timeout parameter is > -1.
- * <p>
+ * Notice that the changed/removed callbacks are not used when the timeout parameter is greater than -1.
*
* -1 means no timeout at all (default). 0 means that invocation on a missing service will fail
* immediately. A positive number represents the max timeout in millis to wait for the service availability.
*
- * <p> Sample Code:<p>
+ * Sample Code:
* <blockquote><pre>
* @Component
* class MyServer implements Runnable {
@@ -115,6 +121,7 @@
* }
* }
* </pre></blockquote>
+ * @return the wait time when the dependency is unavailable
*/
long timeout() default -1;
@@ -127,6 +134,7 @@
* your named dependencies, which will then be calculated once the init() method returns.
*
* <p> See {@link Init} annotation for an example usage of a dependency dynamically configured from the init method.
+ * @return the dependency name used to dynamically configure the filter and required flag from the init callback.
*/
String name() default "";
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Start.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Start.java
index da61b70..ec9e31a 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Start.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Start.java
@@ -30,7 +30,6 @@
* 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>
*
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Stop.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Stop.java
index 672b7ea..f963db0 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Stop.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Stop.java
@@ -29,7 +29,6 @@
* 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>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Unregistered.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Unregistered.java
index c59a435..26ac430 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Unregistered.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Unregistered.java
@@ -28,7 +28,6 @@
* At this point, the component has been unregistered from the OSGI registry (if it provides some services).
* The method must not take any parameters.
*
- * <p>
* <h3>Usage Examples</h3>
* <blockquote>
*
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
index b3f3758..2cbc288 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
@@ -38,6 +38,7 @@
import org.apache.felix.dm.annotation.api.Inject;
import org.apache.felix.dm.annotation.api.LifecycleController;
import org.apache.felix.dm.annotation.api.Registered;
+import org.apache.felix.dm.annotation.api.RepeatableProperty;
import org.apache.felix.dm.annotation.api.ResourceAdapterService;
import org.apache.felix.dm.annotation.api.ResourceDependency;
import org.apache.felix.dm.annotation.api.ServiceDependency;
@@ -72,6 +73,7 @@
private final static String A_LIFCLE_CTRL = LifecycleController.class.getName();
private final static String A_COMPONENT = Component.class.getName();
+ private final static String A_REPEATABLE_PROPERTY = RepeatableProperty.class.getName();
private final static String A_SERVICE_DEP = ServiceDependency.class.getName();
private final static String A_CONFIGURATION_DEPENDENCY = ConfigurationDependency.class.getName();
private final static String A_BUNDLE_DEPENDENCY = BundleDependency.class.getName();
@@ -93,7 +95,7 @@
private String m_method;
private String m_descriptor;
private Set<String> m_dependencyNames = new HashSet<String>();
- private List<EntryWriter> m_writers = new ArrayList<EntryWriter>(); // Last elem is either Service or AspectService
+ private List<EntryWriter> m_writers = new ArrayList<EntryWriter>();
private MetaType m_metaType;
private String m_startMethod;
private String m_stopMethod;
@@ -109,11 +111,9 @@
private String m_componentField;
private String m_registeredMethod;
private String m_unregisteredMethod;
-
- /**
- * This class represents a DependencyManager component descriptor entry.
- * (Service, a ServiceDependency ... see EntryType enum).
- */
+ private Annotation m_repeatableProperty;
+ private final List<EntryType> m_componentTypes = Arrays.asList(EntryType.Component, EntryType.AspectService, EntryType.AdapterService,
+ EntryType.BundleAdapterService, EntryType.ResourceAdapterService, EntryType.FactoryConfigurationAdapterService);
/**
* Makes a new Collector for parsing a given class.
@@ -263,7 +263,11 @@
else if (annotation.getName().getFQN().equals(A_INJECT))
{
parseInject(annotation);
- }
+ }
+ else if (annotation.getName().getFQN().equals(A_REPEATABLE_PROPERTY))
+ {
+ parseRepeatableProperties(annotation);
+ }
}
/**
@@ -278,10 +282,24 @@
return false;
}
- // We must have at least a Service annotation.
- checkServiceDeclared(EntryType.Component, EntryType.AspectService, EntryType.AdapterService,
- EntryType.BundleAdapterService,
- EntryType.ResourceAdapterService, EntryType.FactoryConfigurationAdapterService);
+ // We must have at least a valid component annotation type (component, aspect, or adapters)
+
+ EntryWriter componentWriter = m_writers.stream()
+ .filter(writer -> m_componentTypes.indexOf(writer.getEntryType()) != -1)
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException(": the class " + m_className + " must be annotated with either one of the following types: " + m_componentTypes));
+
+ // Add any repeated @Property annotation to the component (or to the aspect, or adapter).
+
+ if (m_repeatableProperty != null)
+ {
+ Object[] properties = m_repeatableProperty.get("value");
+ for (Object property : properties)
+ {
+ // property is actually a @Property annotation.
+ parseProperty((Annotation) property, componentWriter);
+ }
+ }
StringBuilder sb = new StringBuilder();
sb.append("Parsed annotation for class ");
@@ -328,6 +346,15 @@
return m_exportService;
}
+ /**
+ * Parses a Property annotation that is applied on the component class.
+ * @param property the Property annotation.
+ */
+ private void parseRepeatableProperties(Annotation repeatedProperties)
+ {
+ m_repeatableProperty = repeatedProperties;
+ }
+
private void parseComponentAnnotation(Annotation annotation)
{
EntryWriter writer = new EntryWriter(EntryType.Component);
@@ -340,7 +367,7 @@
writer.put(EntryParam.impl, m_className);
// properties attribute
- parseProperties(annotation, EntryParam.properties, writer);
+ parseProperties(annotation, writer);
// provides attribute.
if (writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService) == 0)
@@ -642,7 +669,7 @@
writer.put(EntryParam.impl, m_className);
// Parse Aspect properties.
- parseProperties(annotation, EntryParam.properties, writer);
+ parseProperties(annotation, writer);
// Parse field/added/changed/removed attributes
parseAspectOrAdapterCallbackMethods(annotation, writer);
@@ -727,7 +754,7 @@
writer.putClass(annotation, EntryParam.adapteeService);
// Parse Adapter properties.
- parseProperties(annotation, EntryParam.properties, writer);
+ parseProperties(annotation, writer);
// Parse the provided adapter service (use directly implemented interface by default).
if (writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService) == 0)
@@ -774,7 +801,7 @@
Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE).toString());
// Parse Adapter properties.
- parseProperties(annotation, EntryParam.properties, writer);
+ parseProperties(annotation, writer);
// Parse the optional adapter service (use directly implemented interface by default).
if (writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService) == 0)
@@ -813,7 +840,7 @@
}
// Parse Adapter properties.
- parseProperties(annotation, EntryParam.properties, writer);
+ parseProperties(annotation, writer);
// Parse the provided adapter service (use directly implemented interface by default).
if (writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService) == 0)
@@ -862,7 +889,7 @@
}
// Parse Adapter properties.
- parseProperties(annotation, EntryParam.properties, writer);
+ parseProperties(annotation, writer);
// Parse optional meta types for configuration description.
parseMetaTypes(annotation, factoryPid, true);
@@ -1036,96 +1063,111 @@
* }
* }
*
- * @param annotation the annotation where the Param annotation is defined
- * @param attribute the attribute name which is of Param type
- * @param writer the object where the parsed attributes are written
+ * @param component the component annotation which contains a "properties" attribute. The component can be either a @Component, or an aspect, or an adapter.
+ * @param writer the object where the parsed attributes are written.
*/
- private void parseProperties(Annotation annotation, EntryParam attribute, EntryWriter writer)
+ private void parseProperties(Annotation component, EntryWriter writer)
+ {
+ Object[] properties = component.get(EntryParam.properties.toString());
+ if (properties != null)
+ {
+ for (Object property : properties)
+ {
+ Annotation propertyAnnotation = (Annotation) property;
+ parseProperty(propertyAnnotation, writer);
+ }
+ }
+ }
+
+ /**
+ * Parses a Property annotation. The result is added to the associated writer object
+ * @param annotation the @Property annotation.
+ * @param writer the writer object where the parsed property will be added to.
+ */
+ private void parseProperty(Annotation property, EntryWriter writer)
{
+ EntryParam attribute = EntryParam.properties;
try
{
- Object[] parameters = annotation.get(attribute.toString());
- if (parameters != null)
+ JSONObject properties = writer.getJsonObject(attribute);
+ if (properties == null) {
+ properties = new JSONObject();
+ }
+
+ String name = (String) property.get("name");
+ String type = parseClassAttrValue(property.get("type"));
+ Class<?> classType;
+ try
{
- JSONObject properties = new JSONObject();
- for (Object p : parameters)
- {
- Annotation a = (Annotation) p;
- String name = (String) a.get("name");
+ classType = (type == null) ? String.class : Class.forName(type);
+ }
+ catch (ClassNotFoundException e)
+ {
+ // Theorically impossible
+ throw new IllegalArgumentException("Invalid Property type " + type
+ + " from annotation " + property + " in class " + m_className);
+ }
- String type = parseClassAttrValue(a.get("type"));
- Class<?> classType;
- try
- {
- classType = (type == null) ? String.class : Class.forName(type);
- }
- catch (ClassNotFoundException e)
- {
- // Theorically impossible
- throw new IllegalArgumentException("Invalid Property type " + type
- + " from annotation " + annotation + " in class " + m_className);
- }
+ Object[] values;
- Object[] values;
+ if ((values = property.get("value")) != null)
+ {
+ values = checkPropertyType(name, classType, values);
+ addProperty(properties, name, values, classType);
+ }
+ else if ((values = property.get("values")) != null)
+ { // deprecated
+ values = checkPropertyType(name, classType, values);
+ addProperty(properties, name, values, classType);
+ }
+ else if ((values = property.get("longValue")) != null)
+ {
+ addProperty(properties, name, values, Long.class);
+ }
+ else if ((values = property.get("doubleValue")) != null)
+ {
+ addProperty(properties, name, values, Double.class);
+ }
+ else if ((values = property.get("floatValue")) != null)
+ {
+ addProperty(properties, name, values, Float.class);
+ }
+ else if ((values = property.get("intValue")) != null)
+ {
+ addProperty(properties, name, values, Integer.class);
+ }
+ else if ((values = property.get("byteValue")) != null)
+ {
+ addProperty(properties, name, values, Byte.class);
+ }
+ else if ((values = property.get("charValue")) != null)
+ {
+ addProperty(properties, name, values, Character.class);
+ }
+ else if ((values = property.get("booleanValue")) != null)
+ {
+ addProperty(properties, name, values, Boolean.class);
+ }
+ else if ((values = property.get("shortValue")) != null)
+ {
+ addProperty(properties, name, values, Short.class);
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Missing Property value from annotation " + property + " in class " + m_className);
+ }
- if ((values = a.get("value")) != null)
- {
- values = checkPropertyType(name, classType, values);
- addProperty(properties, name, values, classType);
- }
- else if ((values = a.get("values")) != null)
- { // deprecated
- values = checkPropertyType(name, classType, values);
- addProperty(properties, name, values, classType);
- }
- else if ((values = a.get("longValue")) != null)
- {
- addProperty(properties, name, values, Long.class);
- }
- else if ((values = a.get("doubleValue")) != null)
- {
- addProperty(properties, name, values, Double.class);
- }
- else if ((values = a.get("floatValue")) != null)
- {
- addProperty(properties, name, values, Float.class);
- }
- else if ((values = a.get("intValue")) != null)
- {
- addProperty(properties, name, values, Integer.class);
- }
- else if ((values = a.get("byteValue")) != null)
- {
- addProperty(properties, name, values, Byte.class);
- }
- else if ((values = a.get("charValue")) != null)
- {
- addProperty(properties, name, values, Character.class);
- }
- else if ((values = a.get("booleanValue")) != null)
- {
- addProperty(properties, name, values, Boolean.class);
- }
- else if ((values = a.get("shortValue")) != null)
- {
- addProperty(properties, name, values, Short.class);
- }
- else
- {
- throw new IllegalArgumentException("Missing Property value from annotation "
- + annotation + " in class " + m_className);
- }
- }
+ if (properties.length() > 0) {
writer.putJsonObject(attribute, properties);
}
}
catch (JSONException e)
{
- throw new IllegalArgumentException("UNexpected exception while parsing Property from annotation "
- + annotation + " in class " + m_className, e);
+ throw new IllegalArgumentException("Unexpected exception while parsing Property from class " + m_className, e);
}
}
-
+
/**
* Checks if a property contains values that are compatible with a give primitive type.
*
@@ -1291,35 +1333,6 @@
}
/**
- * Checks if the class is annotated with some given annotations. Notice that the Service
- * is always parsed at end of parsing, so, we have to check the last element of our m_writers
- * List.
- * @return true if one of the provided annotations has been found from the parsed class.
- */
- private void checkServiceDeclared(EntryType... types)
- {
- boolean ok = false;
- if (m_writers.size() > 0)
- {
- for (EntryType type: types)
- {
- if (m_writers.get(m_writers.size() - 1).getEntryType() == type)
- {
- ok = true;
- break;
- }
- }
- }
-
- if (!ok)
- {
- throw new IllegalStateException(
- ": the class must be annotated with either one of the following types: "
- + Arrays.toString(types));
- }
- }
-
- /**
* This method checks if the @Registered and/or @Unregistered annotations have been defined
* while they should not, because the component does not provide a service.
*/
diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java
index 89cdb82..25cb4e6 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java
@@ -118,6 +118,22 @@
{
m_json.put(param.toString(), jsonObject);
}
+
+ /**
+ * Gets a json object associated to the given parameter name.
+ * @throws JSONException
+ */
+ public JSONObject getJsonObject(EntryParam param)
+ {
+ try
+ {
+ return (JSONObject) m_json.get(param.toString());
+ }
+ catch (JSONException e)
+ {
+ return null;
+ }
+ }
/**
* Get a String attribute value from an annotation and write it into this descriptor entry.
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/Felix4357.java b/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/Felix4357.java
index f2948ea..d585000 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/Felix4357.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/Felix4357.java
@@ -33,49 +33,37 @@
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-@Component(properties={
- @Property(name="v1", value="s"),
- @Property(name="v2", value={"s1", "s2"}),
- @Property(name="v3", values={"s1", "s2"}),
-
- @Property(name="v4", value="1", type=Long.class),
- @Property(name="v5", longValue=1),
- @Property(name="v6", longValue={1, 2}),
-
- @Property(name="v7", value="1", type=Double.class),
- @Property(name="v8", doubleValue=1),
- @Property(name="v9", doubleValue={1, 2}),
-
- @Property(name="v10", value="1", type=Float.class),
- @Property(name="v11", floatValue=1),
- @Property(name="v12", floatValue={1, 2}),
-
- @Property(name="v13", value="1", type=Integer.class),
- @Property(name="v14", intValue=1),
- @Property(name="v15", intValue={1, 2}),
-
- @Property(name="v16", value="65", type=Byte.class),
- @Property(name="v17", byteValue=65),
- @Property(name="v18", byteValue={65, 66}),
-
- @Property(name="v19", value="A", type=Character.class),
- @Property(name="v20", charValue='A'),
- @Property(name="v21", charValue={'A', 'B'}),
-
- @Property(name="v22", value="true", type=Boolean.class),
- @Property(name="v23", booleanValue=true),
- @Property(name="v24", booleanValue={true, false}),
-
- @Property(name="v25", value="1", type=Short.class),
- @Property(name="v26", shortValue=1),
- @Property(name="v27", shortValue={1, 2}),
-
- @Property(name="v28", value="65", type=Character.class),
- @Property(name="v29", charValue=65),
- @Property(name="v30", charValue={65, 66}),
- },
- provides=Felix4357.class
-)
+@Component(provides=Felix4357.class)
+@Property(name="v1", value="s")
+@Property(name="v2", value={"s1", "s2"})
+@Property(name="v3", values={"s1", "s2"})
+@Property(name="v4", value="1", type=Long.class)
+@Property(name="v5", longValue=1)
+@Property(name="v6", longValue={1, 2})
+@Property(name="v7", value="1", type=Double.class)
+@Property(name="v8", doubleValue=1)
+@Property(name="v9", doubleValue={1, 2})
+@Property(name="v10", value="1", type=Float.class)
+@Property(name="v11", floatValue=1)
+@Property(name="v12", floatValue={1, 2})
+@Property(name="v13", value="1", type=Integer.class)
+@Property(name="v14", intValue=1)
+@Property(name="v15", intValue={1, 2})
+@Property(name="v16", value="65", type=Byte.class)
+@Property(name="v17", byteValue=65)
+@Property(name="v18", byteValue={65, 66})
+@Property(name="v19", value="A", type=Character.class)
+@Property(name="v20", charValue='A')
+@Property(name="v21", charValue={'A', 'B'})
+@Property(name="v22", value="true", type=Boolean.class)
+@Property(name="v23", booleanValue=true)
+@Property(name="v24", booleanValue={true, false})
+@Property(name="v25", value="1", type=Short.class)
+@Property(name="v26", shortValue=1)
+@Property(name="v27", shortValue={1, 2})
+@Property(name="v28", value="65", type=Character.class)
+@Property(name="v29", charValue=65)
+@Property(name="v30", charValue={65, 66})
public class Felix4357 {
public final static String ENSURE = "Felix4357";
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ResourceAdapterServiceTestWithPublisher.java b/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ResourceAdapterServiceTestWithPublisher.java
index 5b77a33..f2f923d 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ResourceAdapterServiceTestWithPublisher.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ResourceAdapterServiceTestWithPublisher.java
@@ -160,8 +160,9 @@
}
}
}
-
- @ResourceAdapterService(filter = "(&(path=/path/to/test1.txt)(host=localhost))", properties = {@Property(name = "foo", value = "bar")}, propagate = true)
+
+ @ResourceAdapterService(filter = "(&(path=/path/to/test1.txt)(host=localhost))", propagate = true)
+ @Property(name = "foo", value = "bar")
public static class ProviderImpl implements Provider {
@LifecycleController
volatile Runnable m_publisher; // injected and used to register our service