Removed TemporalServiceDependency, but added a timeout attribute in the ServiceDependency annotation
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@947788 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/ServiceDependency.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/ServiceDependency.java
index 85bb686..e265a15 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/ServiceDependency.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/ServiceDependency.java
@@ -66,4 +66,42 @@
* The callback method to invoke when the service is lost.
*/
String removed() default "";
+
+ /**
+ * The max time in millis to wait for the dependency availability.
+ * Specifying a positive number allow to block the caller thread between service updates. Only
+ * useful for required stateless dependencies that can be replaced transparently.
+ * A Dynamic Proxy is used to wrap the actual service dependency (which must be an interface).
+ * When the dependency goes away, an attempt is made to replace it with another one which satisfies
+ * the service dependency criteria. If no service replacement is available, then any method invocation
+ * (through the dynamic proxy) will block during a configurable timeout. On timeout, an unchecked
+ * <code>IllegalStateException</code> exception is raised (but the service is not deactivated).<p>
+ * Notice that the changed/removed callbacks are not used when the timeout parameter is > -1.
+ * <p>
+ *
+ * -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 millisends to wait for the service availability.
+ *
+ * <p> Sample Code:<p>
+ * <blockquote><pre>
+ * @Service
+ * class MyServer implements Runnable {
+ * @ServiceDependency(timeout=15000)
+ * MyDependency _dependency;.
+ *
+ * @Start
+ * void start() {
+ * (new Thread(this)).start();
+ * }
+ *
+ * public void run() {
+ * try {
+ * _dependency.doWork();
+ * } catch (IllegalStateException e) {
+ * t.printStackTrace();
+ * }
+ * }
+ * </pre></blockquote>
+ */
+ long timeout() default -1;
}
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/TemporalServiceDependency.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/TemporalServiceDependency.java
deleted file mode 100644
index e445adb..0000000
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/TemporalServiceDependency.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.dependency;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotates a method or a field for injecting a Temporal Service Dependency.
- * A Temporal Service dependency can block the caller thread between service updates. Only
- * useful for required stateless dependencies that can be replaced transparently.
- * A Dynamic Proxy is used to wrap the actual service dependency. When the dependency goes
- * away, an attempt is made to replace it with another one which satisfies the service dependency
- * criteria. If no service replacement is available, then any method invocation (through the
- * dynamic proxy) will block during a configurable timeout. On timeout, an unchecked
- * <code>IllegalStateException</code> exception is raised (but the service is not deactivated).<p>
- *
- * <b>Only supports required dependencies</b>
- *
- * <p> Sample Code:<p>
- * <blockquote>
- *
- * <pre>
- * @Service
- * class MyServer implements Runnable {
- * @TemporalServiceDependency(timeout=15000)
- * MyDependency _dependency;.
- *
- * @Start
- * void start() {
- * (new Thread(this)).start();
- * }
- *
- * public void run() {
- * try {
- * _dependency.doWork();
- * } catch (IllegalStateException e) {
- * t.printStackTrace();
- * }
- * }
- * </pre>
- *
- * </blockquote>
- */
-@Retention(RetentionPolicy.CLASS)
-@Target( { ElementType.METHOD, ElementType.FIELD })
-public @interface TemporalServiceDependency
-{
- /**
- * Sets the timeout for this temporal dependency. Specifying a timeout value of zero means that there is no timeout period,
- * and an invocation on a missing service will fail immediately.
- *
- * @param timeout the dependency timeout value greater or equals to 0
- * @throws IllegalArgumentException if the timeout is negative
- * @return this temporal dependency
- */
- long timeout() default 30000L;
-
- /**
- * Returns the Service dependency type (by default, the type is method parameter type).
- * @return the Service dependency type.
- */
- Class<?> service() default Object.class;
-
- /**
- * Returns the Service dependency OSGi filter.
- * @return The Service dependency filter.
- */
- String filter() default "";
-
- /**
- * Returns the class for the default implementation, if the dependency is not available.
- * @return The default class used when the dependency is not available.
- */
- Class<?> defaultImpl() default Object.class;
-
- /**
- * 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.
- */
- String added() default "";
-}
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
index 83d3a48..c1b57fe 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
@@ -42,7 +42,6 @@
import org.apache.felix.dm.annotation.api.dependency.ConfigurationDependency;
import org.apache.felix.dm.annotation.api.dependency.ResourceDependency;
import org.apache.felix.dm.annotation.api.dependency.ServiceDependency;
-import org.apache.felix.dm.annotation.api.dependency.TemporalServiceDependency;
import org.osgi.framework.Bundle;
import aQute.lib.osgi.Annotation;
@@ -68,8 +67,6 @@
+ ServiceDependency.class.getName().replace('.', '/') + ";";
private final static String A_CONFIGURATION_DEPENDENCY = "L"
+ ConfigurationDependency.class.getName().replace('.', '/') + ";";
- private final static String A_TEMPORAL_SERVICE_DEPENDENCY = "L"
- + TemporalServiceDependency.class.getName().replace('.', '/') + ";";
private final static String A_BUNDLE_DEPENDENCY = "L"
+ BundleDependency.class.getName().replace('.', '/') + ";";
private final static String A_RESOURCE_DEPENDENCY = "L"
@@ -239,16 +236,12 @@
}
else if (annotation.getName().equals(A_SERVICE_DEP))
{
- parseServiceDependencyAnnotation(annotation, false);
+ parseServiceDependencyAnnotation(annotation);
}
else if (annotation.getName().equals(A_CONFIGURATION_DEPENDENCY))
{
parseConfigurationDependencyAnnotation(annotation);
}
- else if (annotation.getName().equals(A_TEMPORAL_SERVICE_DEPENDENCY))
- {
- parseServiceDependencyAnnotation(annotation, true);
- }
else if (annotation.getName().equals(A_BUNDLE_DEPENDENCY))
{
parseBundleDependencyAnnotation(annotation);
@@ -317,13 +310,12 @@
}
/**
- * Parses a ServiceDependency or a TemporalServiceDependency Annotation.
+ * Parses a ServiceDependency Annotation.
* @param annotation the ServiceDependency Annotation.
*/
- private void parseServiceDependencyAnnotation(Annotation annotation, boolean temporal)
+ private void parseServiceDependencyAnnotation(Annotation annotation)
{
- EntryWriter writer = new EntryWriter(temporal ? EntryType.TemporalServiceDependency
- : EntryType.ServiceDependency);
+ EntryWriter writer = new EntryWriter(EntryType.ServiceDependency);
m_writers.add(writer);
// service attribute
@@ -365,22 +357,22 @@
// added callback
writer.putString(annotation, EntryParam.added, (!m_isField) ? m_method : null);
- if (temporal)
+ // timeout parameter
+ writer.putString(annotation, EntryParam.timeout, null);
+ Long t = (Long) annotation.get(EntryParam.timeout.toString());
+ if (t != null && t.longValue() < -1)
{
- // timeout attribute (only valid if parsing a temporal service dependency)
- writer.putString(annotation, EntryParam.timeout, null);
+ throw new IllegalArgumentException("Invalid timeout value " + t + " in ServiceDependency annotation in class " + m_className);
}
- else
- {
- // required attribute (not valid if parsing a temporal service dependency)
- writer.putString(annotation, EntryParam.required, null);
+
+ // required attribute (not valid if parsing a temporal service dependency)
+ writer.putString(annotation, EntryParam.required, null);
- // changed callback
- writer.putString(annotation, EntryParam.changed, null);
+ // changed callback
+ writer.putString(annotation, EntryParam.changed, null);
- // removed callback
- writer.putString(annotation, EntryParam.removed, null);
- }
+ // removed callback
+ writer.putString(annotation, EntryParam.removed, null);
}
/**
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryType.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryType.java
index bdbd005..4e0997d 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryType.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryType.java
@@ -12,7 +12,6 @@
ResourceAdapterService,
FactoryConfigurationAdapterService,
ServiceDependency,
- TemporalServiceDependency,
ConfigurationDependency,
BundleDependency,
ResourceDependency,
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
index 42fdf89..1b206c3 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
@@ -72,11 +72,7 @@
switch (type)
{
case ServiceDependency:
- dp = createServiceDependency(b, dm, false, instanceBound);
- break;
-
- case TemporalServiceDependency:
- dp = createServiceDependency(b, dm, true, instanceBound);
+ dp = createServiceDependency(b, dm, instanceBound);
break;
case ConfigurationDependency:
@@ -94,8 +90,7 @@
return dp;
}
- private Dependency createServiceDependency(Bundle b, DependencyManager dm, boolean temporal,
- boolean instanceBound)
+ private Dependency createServiceDependency(Bundle b, DependencyManager dm, boolean instanceBound)
throws ClassNotFoundException
{
String service = m_metaData.getString(Params.service);
@@ -105,24 +100,24 @@
Class<?> defaultServiceImplClass =
(defaultServiceImpl != null) ? b.loadClass(defaultServiceImpl) : null;
String added = m_metaData.getString(Params.added, null);
- String changed = temporal ? null : m_metaData.getString(Params.changed, null);
- String removed = temporal ? null : m_metaData.getString(Params.removed, null);
+ long timeout = m_metaData.getLong(Params.timeout, -1L);
+ String changed = timeout != -1 ? null : m_metaData.getString(Params.changed, null);
+ String removed = timeout != -1 ? null : m_metaData.getString(Params.removed, null);
String autoConfigField = m_metaData.getString(Params.autoConfig, null);
boolean required = "true".equals(m_metaData.getString(Params.required, "true"));
- String timeout = m_metaData.getString(Params.timeout, null);
- Dependency dp = createServiceDependency(dm, temporal, serviceClass,
+ Dependency dp = createServiceDependency(dm, serviceClass,
serviceFilter, defaultServiceImplClass, added, changed,
removed, autoConfigField, timeout, required, instanceBound);
return dp;
}
- private Dependency createServiceDependency(DependencyManager dm, boolean temporal,
- Class<?> serviceClass, String serviceFilter, Class<?> defaultServiceImplClass, String added,
- String changed, String removed, String autoConfigField, String timeout, boolean required,
+ private Dependency createServiceDependency(DependencyManager dm, Class<?> serviceClass,
+ String serviceFilter, Class<?> defaultServiceImplClass, String added,
+ String changed, String removed, String autoConfigField, long timeout, boolean required,
boolean instanceBound)
{
- ServiceDependency sd = temporal ? dm.createTemporalServiceDependency()
+ ServiceDependency sd = timeout != -1 ? dm.createTemporalServiceDependency()
: dm.createServiceDependency();
sd.setService(serviceClass, serviceFilter);
if (defaultServiceImplClass != null)
@@ -134,13 +129,9 @@
{
sd.setAutoConfig(autoConfigField);
}
- if (temporal)
+ if (timeout != -1)
{
- // Set the timeout value for a temporal service dependency
- if (timeout != null)
- {
- ((TemporalServiceDependency) sd).setTimeout(Long.parseLong(timeout));
- }
+ ((TemporalServiceDependency) sd).setTimeout(timeout);
// Set required flag (always true for a temporal dependency)
sd.setRequired(true);
}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/JSONMetaData.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/JSONMetaData.java
index 7fc7054..217a01e 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/JSONMetaData.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/JSONMetaData.java
@@ -171,6 +171,51 @@
}
}
+ public long getLong(Params key)
+ {
+ String value = getString(key, null);
+ if (value != null)
+ {
+ try
+ {
+ return Long.parseLong(value);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException("parameter " + key
+ + " is not a long value: "
+ + value);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("missing " + key
+ + " parameter from annotation");
+ }
+ }
+
+ public long getLong(Params key, long def)
+ {
+ String value = getString(key, null);
+ if (value != null)
+ {
+ try
+ {
+ return Long.parseLong(value);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException("parameter " + key
+ + " is not a long value: "
+ + value);
+ }
+ }
+ else
+ {
+ return def;
+ }
+ }
+
public String[] getStrings(Params key)
{
Object array = m_metadata.get(key.toString());
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java
index 7c56a30..166a006 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java
@@ -44,6 +44,16 @@
* Returns a String descriptor entry parameter value.
*/
int getInt(Params key, int def);
+
+ /**
+ * Returns a String descriptor entry parameter value.
+ */
+ long getLong(Params key);
+
+ /**
+ * Returns a String descriptor entry parameter value.
+ */
+ long getLong(Params key, long def);
/**
* Returns a String array descriptor entry parameter value.
diff --git a/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/temporal/TemporalTest.java b/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/temporal/TemporalTest.java
index 803f3a6..b6288d7 100644
--- a/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/temporal/TemporalTest.java
+++ b/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/temporal/TemporalTest.java
@@ -22,7 +22,6 @@
import org.apache.felix.dm.annotation.api.Start;
import org.apache.felix.dm.annotation.api.Stop;
import org.apache.felix.dm.annotation.api.dependency.ServiceDependency;
-import org.apache.felix.dm.annotation.api.dependency.TemporalServiceDependency;
import org.apache.felix.dm.test.bundle.annotation.sequencer.Sequencer;
/**
@@ -36,7 +35,7 @@
@ServiceDependency
Sequencer m_sequencer;
- @TemporalServiceDependency(timeout = 1000L, filter = "(test=temporal)")
+ @ServiceDependency(timeout = 1000L, filter = "(test=temporal)")
Runnable m_service;
@Start