metatype support
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@907340 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/annotation/pom.xml b/dependencymanager/annotation/pom.xml
index 146d7f7..b67d94c 100644
--- a/dependencymanager/annotation/pom.xml
+++ b/dependencymanager/annotation/pom.xml
@@ -46,6 +46,12 @@
</dependency>
<dependency>
+ <groupId>com.thoughtworks.xstream</groupId>
+ <artifactId>xstream</artifactId>
+ <version>1.3.1</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
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 aebda9c..dbfb735 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
@@ -33,7 +33,7 @@
import org.apache.felix.dm.annotation.api.ConfigurationDependency;
import org.apache.felix.dm.annotation.api.Destroy;
import org.apache.felix.dm.annotation.api.Init;
-import org.apache.felix.dm.annotation.api.Param;
+import org.apache.felix.dm.annotation.api.Properties;
import org.apache.felix.dm.annotation.api.Service;
import org.apache.felix.dm.annotation.api.ServiceDependency;
import org.apache.felix.dm.annotation.api.Start;
@@ -65,6 +65,8 @@
+ ConfigurationDependency.class.getName().replace('.', '/') + ";";
private final static String A_TEMPORAL_SERVICE_DEPENDENCY = "L"
+ TemporalServiceDependency.class.getName().replace('.', '/') + ";";
+ private final static String A_PROPERTIES = "L"
+ + Properties.class.getName().replace('.', '/') + ";";
private Reporter m_reporter;
private String m_className;
@@ -75,6 +77,7 @@
private String m_descriptor;
private Set<String> m_methods = new HashSet<String>();
private List<Info> m_infos = new ArrayList<Info>();
+ private MetaType m_metaType;
// 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");
@@ -254,10 +257,11 @@
* Makes a new Collector for parsing a given class.
* @param reporter the object used to report logs.
*/
- public AnnotationCollector(Reporter reporter)
+ public AnnotationCollector(Reporter reporter, MetaType metaType)
{
m_reporter = reporter;
m_infos.add(new Info(EntryTypes.Service));
+ m_metaType = metaType;
}
/**
@@ -367,6 +371,10 @@
else if (annotation.getName().equals(A_TEMPORAL_SERVICE_DEPENDENCY))
{
parseServiceDependencyAnnotation(annotation, true);
+ }
+ else if (annotation.getName().equals(A_PROPERTIES))
+ {
+ parsePropertiesMetaData(annotation);
}
}
@@ -486,6 +494,46 @@
}
/**
+ * Parses a Properties annotation which declares Config Admin Properties meta data.
+ * @param properties the Properties annotation to be parsed.
+ */
+ private void parsePropertiesMetaData(Annotation properties)
+ {
+ String propertiesPid = get(properties, "pid", m_className);
+ String propertiesHeading = properties.get("heading");
+ String propertiesDesc = properties.get("description");
+
+ MetaType.OCD ocd = new MetaType.OCD(propertiesPid, propertiesHeading, propertiesDesc);
+ for (Object p : (Object[]) properties.get("properties"))
+ {
+ Annotation property = (Annotation) p;
+ String heading = property.get("heading");
+ String id = property.get("id");
+ String type = (String) property.get("type");
+ type = (type != null) ? parseClass(type, m_classPattern, 1) : null;
+ Object[] defaults = (Object[]) property.get("defaults");
+ String description = property.get("description");
+ Integer cardinality = property.get("cardinality");
+ Boolean required = property.get("required");
+
+ MetaType.AD ad = new MetaType.AD(id, type, defaults, heading, description, cardinality, required);
+ Object[] options = property.get("options");
+ if (options != null) {
+ for (Object o : (Object[]) property.get("options"))
+ {
+ Annotation option = (Annotation) o;
+ ad.add(new MetaType.Option((String) option.get("name"), (String) option.get("value")));
+ }
+ }
+ ocd.add(ad);
+ }
+
+ m_metaType.add(ocd);
+ MetaType.Designate designate = new MetaType.Designate(propertiesPid);
+ m_metaType.add(designate);
+ }
+
+ /**
* Parses a class.
* @param clazz the class to be parsed (the package is "/" separated).
* @param pattern the pattern used to match the class.
@@ -523,6 +571,20 @@
}
/**
+ * Get an annotation attribute, and return a default value if its not present.
+ * @param <T> the type of the variable which is assigned to the return value of this method.
+ * @param properties The annotation we are parsing
+ * @param name the attribute name to get from the annotation
+ * @param defaultValue the default value to return if the attribute is not found in the annotation
+ * @return the annotation attribute value, or the defaultValue if not found
+ */
+ private <T> T get(Annotation properties, String name, T defaultValue)
+ {
+ T value = (T) properties.get(name);
+ return value != null ? value : defaultValue;
+ }
+
+ /**
* Finishes up the class parsing. This method must be called once the parseClassFileWithCollector method has returned.
*/
public void finish()
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationPlugin.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationPlugin.java
index db5ea2a..0709918 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationPlugin.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationPlugin.java
@@ -56,6 +56,13 @@
{
analyzer.getJar().putResource(entry.getKey(), entry.getValue());
}
+
+ // Inser the metatype resource, if any.
+ Resource metaType = generator.getMetaTypeResource();
+ if (metaType != null)
+ {
+ analyzer.getJar().putResource("OSGI-INF/metatype/metatype.xml", metaType);
+ }
}
return false;
}
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/DescriptorGenerator.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/DescriptorGenerator.java
index 82f0705..55dad6f 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/DescriptorGenerator.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/DescriptorGenerator.java
@@ -22,6 +22,7 @@
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -53,6 +54,11 @@
Map<String, Resource> m_resources = new HashMap<String, Resource>();
/**
+ * This is the generated MetaType XML descriptor, if any Properties/Property annotations have been found.
+ */
+ private Resource m_metaTypeResource;
+
+ /**
* Creates a new descriptor generator.
* @param analyzer The bnd analyzer used to lookup classes containing DM annotations.
*/
@@ -76,16 +82,19 @@
// Try to locate any classes in the wildcarded universe
// that are annotated with the DependencyManager "Service" annotations.
Collection<Clazz> expanded = m_analyzer.getClasses("",
- // Then limit the ones with component annotations.
+ // Then limit the ones with component annotations.
QUERY.ANNOTATION.toString(), Service.class.getName(),
// Parse everything
QUERY.NAMED.toString(), "*");
+ // Create the object which will collect Config Admin MetaTypes.
+ MetaType metaType = new MetaType();
+
for (Clazz c : expanded)
{
clazz = c;
// Let's parse all annotations from that class !
- AnnotationCollector reader = new AnnotationCollector(this);
+ AnnotationCollector reader = new AnnotationCollector(this, metaType);
c.parseClassFileWithCollector(reader);
reader.finish();
// And store the generated component descriptors in our resource list.
@@ -95,6 +104,10 @@
annotationsFound = true;
}
+ // If some Meta Types have been parsed, then creates the corresponding resource file.
+ if (metaType.getSize() > 0) {
+ m_metaTypeResource = createMetaTypeResource(metaType);
+ }
return annotationsFound;
}
catch (Throwable err)
@@ -106,7 +119,7 @@
sb.append(" from class " + clazz);
}
sb.append(": ");
- sb.append(err.toString());
+ sb.append(parse(err));
error(sb.toString(), err.getCause());
return false;
}
@@ -147,6 +160,13 @@
}
/**
+ * Returns the MetaType resource.
+ */
+ public Resource getMetaTypeResource() {
+ return m_metaTypeResource;
+ }
+
+ /**
* Creates a bnd resource that contains the generated dm descriptor.
* @param collector
* @return
@@ -162,4 +182,33 @@
out.close();
return new EmbeddedResource(data, 0);
}
+
+ /**
+ * Creates a bnd resource that contains the generated metatype descriptor.
+ * @param metaType the Object that has collected all meta type informations.
+ * @return the meta type resource
+ * @throws IOException on any errors
+ */
+ private Resource createMetaTypeResource(MetaType metaType) throws IOException
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
+ metaType.writeTo(pw);
+ pw.close();
+ byte[] data = out.toByteArray();
+ out.close();
+ return new EmbeddedResource(data, 0);
+ }
+
+ /**
+ * Parse an exception into a string.
+ * @param e The exception to parse
+ * @return the parsed exception
+ */
+ private static String parse(Throwable e) {
+ StringWriter buffer = new StringWriter();
+ PrintWriter pw = new PrintWriter(buffer);
+ e.printStackTrace(pw);
+ return (buffer.toString());
+ }
}