added ResourceAdapter and ResourceDependency annotations.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@919863 13f79535-47bb-0310-9956-ffa450edef68
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
new file mode 100644
index 0000000..cd6c689
--- /dev/null
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceAdapterService.java
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+/**
+ * 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.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.TYPE)
+public @interface ResourceAdapterService
+{
+ /**
+ * The filter condition to use with the resource.
+ */
+ String filter();
+
+ /**
+ * The interface to use when registering adapters
+ */
+ Class<?> service() default Object.class;
+
+ /**
+ * Additional properties to use with the adapter service registration
+ */
+ Param[] properties() default {};
+
+ /**
+ * <code>true</code> if properties from the resource should be propagated to the service.
+ */
+ 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
new file mode 100644
index 0000000..c4d2823
--- /dev/null
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ResourceDependency.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD, ElementType.FIELD})
+public @interface ResourceDependency
+{
+ /**
+ * 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 "";
+
+ /**
+ * Returns the callback method to be invoked when the service properties have changed.
+ */
+ String changed() default "";
+
+ /**
+ * Returns the callback method to invoke when the service is lost.
+ */
+ String removed() default "";
+
+ /**
+ * 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
+ */
+ boolean propagate() default false;
+}
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 db8754d..bf47e81 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
@@ -38,6 +38,8 @@
import org.apache.felix.dm.annotation.api.Destroy;
import org.apache.felix.dm.annotation.api.Init;
import org.apache.felix.dm.annotation.api.Properties;
+import org.apache.felix.dm.annotation.api.ResourceAdapterService;
+import org.apache.felix.dm.annotation.api.ResourceDependency;
import org.apache.felix.dm.annotation.api.Service;
import org.apache.felix.dm.annotation.api.ServiceDependency;
import org.apache.felix.dm.annotation.api.Start;
@@ -72,6 +74,8 @@
+ TemporalServiceDependency.class.getName().replace('.', '/') + ";";
private final static String A_BUNDLE_DEPENDENCY = "L"
+ BundleDependency.class.getName().replace('.', '/') + ";";
+ private final static String A_RESOURCE_DEPENDENCY = "L"
+ + ResourceDependency.class.getName().replace('.', '/') + ";";
private final static String A_PROPERTIES = "L"
+ Properties.class.getName().replace('.', '/') + ";";
private final static String A_ASPECT_SERVICE = "L"
@@ -80,6 +84,8 @@
+ AdapterService.class.getName().replace('.', '/') + ";";
private final static String A_BUNDLE_ADAPTER_SERVICE = "L"
+ BundleAdapterService.class.getName().replace('.', '/') + ";";
+ private final static String A_RESOURCE_ADAPTER_SERVICE = "L"
+ + ResourceAdapterService.class.getName().replace('.', '/') + ";";
private Reporter m_reporter;
private String m_className;
@@ -97,8 +103,8 @@
private String m_destroyMethod;
private String m_compositionMethod;
- // Pattern used to parse the class parameter from the bind methods ("bind(Type)" or "bind(Map, Type)")
- private final static Pattern m_bindClassPattern = Pattern.compile("\\((Ljava/util/Map;)?L([^;]+);\\)V");
+ // Pattern used to parse the class parameter from the bind methods ("bind(Type)" or "bind(Map, Type)" or "bind(BundleContext, Type)"
+ private final static Pattern m_bindClassPattern = Pattern.compile("\\((L[^;]+;)?L([^;]+);\\)V");
// Pattern used to parse classes from class descriptors;
private final static Pattern m_classPattern = Pattern.compile("L([^;]+);");
@@ -116,10 +122,12 @@
AspectService,
AdapterService,
BundleAdapterService,
+ ResourceAdapterService,
ServiceDependency,
TemporalServiceDependency,
ConfigurationDependency,
BundleDependency,
+ ResourceDependency
};
// List of component descriptor parameters
@@ -375,6 +383,10 @@
{
parseBundleAdapterService(annotation);
}
+ else if (annotation.getName().equals(A_RESOURCE_ADAPTER_SERVICE))
+ {
+ parseResourceAdapterService(annotation);
+ }
else if (annotation.getName().equals(A_INIT))
{
checkMethod(m_voidMethodPattern);
@@ -420,6 +432,10 @@
{
parseBundleDependencyAnnotation(annotation);
}
+ else if (annotation.getName().equals(A_RESOURCE_DEPENDENCY))
+ {
+ parseRersourceDependencyAnnotation(annotation);
+ }
}
/**
@@ -432,7 +448,7 @@
m_infos.add(info);
// Register previously parsed Init/Start/Stop/Destroy/Composition annotations
- addInitStartStopDestroyCompositionParams(info);
+ addCommonServiceParams(info);
// impl attribute
info.addParam(Params.impl, m_className);
@@ -450,7 +466,7 @@
info.addParam(annotation, Params.factoryMethod, null);
}
- private void addInitStartStopDestroyCompositionParams(Info info)
+ private void addCommonServiceParams(Info info)
{
if (m_initMethod != null) {
info.addParam(Params.init, m_initMethod);
@@ -608,7 +624,7 @@
m_infos.add(info);
// Register previously parsed Init/Start/Stop/Destroy/Composition annotations
- addInitStartStopDestroyCompositionParams(info);
+ addCommonServiceParams(info);
// factory attribute
info.addClassParam(annotation, Params.factory, null);
@@ -665,7 +681,7 @@
m_infos.add(info);
// Register previously parsed Init/Start/Stop/Destroy/Composition annotations
- addInitStartStopDestroyCompositionParams(info);
+ addCommonServiceParams(info);
// Generate Adapter Implementation
info.addParam(Params.impl, m_className);
@@ -718,7 +734,7 @@
m_infos.add(info);
// Register previously parsed Init/Start/Stop/Destroy/Composition annotations
- addInitStartStopDestroyCompositionParams(info);
+ addCommonServiceParams(info);
// Generate Adapter Implementation
info.addParam(Params.impl, m_className);
@@ -764,6 +780,59 @@
info.addParam(annotation, Params.propagate, Boolean.FALSE);
}
+ /**
+ * Parses a BundleAdapterService annotation.
+ * @param annotation
+ */
+ private void parseResourceAdapterService(Annotation annotation)
+ {
+ Info info = new Info(EntryTypes.ResourceAdapterService);
+ m_infos.add(info);
+
+ // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
+ addCommonServiceParams(info);
+
+ // Generate Adapter Implementation
+ info.addParam(Params.impl, m_className);
+
+ // Parse resource filter
+ String filter = annotation.get(Params.filter.toString());
+ if (filter != null)
+ {
+ Verifier.verifyFilter(filter, 0);
+ info.addParam(Params.filter, filter);
+ }
+
+ // Parse Adapter properties.
+ parseParameters(annotation, Params.properties, info);
+
+ // Parse the optional adapter service (use directly implemented interface by default).
+ Object service = annotation.get(Params.service.toString());
+ if (service == null) {
+ if (m_interfaces == null)
+ {
+ throw new IllegalStateException("Invalid ResourceAdapterService annotation: " +
+ "the service attribute has not been set and the class " + m_className +
+ " does not implement any interfaces");
+ }
+ if (m_interfaces.length != 1)
+ {
+ throw new IllegalStateException("Invalid ResourceAdapterService annotation: " +
+ "the service attribute has not been set and the class " + m_className +
+ " implements more than one interface");
+ }
+
+ info.addParam(Params.service, m_interfaces[0]);
+ } else
+ {
+ checkClassImplements(annotation, Params.service);
+ info.addClassParam(annotation, Params.service, null);
+ }
+
+ // Parse propagate attribute
+ info.addParam(annotation, Params.propagate, Boolean.FALSE);
+ }
+
private void parseBundleDependencyAnnotation(Annotation annotation)
{
Info info = new Info(EntryTypes.BundleDependency);
@@ -784,6 +853,25 @@
info.addParam(annotation, Params.propagate, null);
}
+ private void parseRersourceDependencyAnnotation(Annotation annotation)
+ {
+ Info info = new Info(EntryTypes.ResourceDependency);
+ m_infos.add(info);
+
+ String filter = annotation.get(Params.filter.toString());
+ if (filter != null)
+ {
+ Verifier.verifyFilter(filter, 0);
+ info.addParam(Params.filter, filter);
+ }
+
+ info.addParam(annotation, Params.added, m_method);
+ info.addParam(annotation, Params.changed, null); // TODO check if "changed" callback exists
+ info.addParam(annotation, Params.removed, null); // TODO check if "removed" callback exists
+ info.addParam(annotation, Params.required, null);
+ info.addParam(annotation, Params.propagate, null);
+ }
+
/**
* Checks if an annotation attribute references an implemented interface.
* @param annotation the parsed annotation
@@ -920,7 +1008,8 @@
}
// We must have at least a Service or an AspectService annotation.
- checkServiceDeclared(EntryTypes.Service, EntryTypes.AspectService, EntryTypes.AdapterService, EntryTypes.BundleAdapterService);
+ checkServiceDeclared(EntryTypes.Service, EntryTypes.AspectService, EntryTypes.AdapterService, EntryTypes.BundleAdapterService,
+ EntryTypes.ResourceAdapterService);
StringBuilder sb = new StringBuilder();
sb.append("Parsed annotation for class ");