- aligned AspectService and AdapterService with new added/changed/removed callbacks introdoced in the API.
- improved annotation plugin logging: a "log" configuration can now be specified in the maven or bnd plugin.
- fixed bug when parsing ConfigurationDependency Annotation: the "updated" field was ignored.
- Generate DM metadata descriptors under META-INF instead of OSGI-INF
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1086716 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AdapterService.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AdapterService.java
index 26507d5..5d0bffd 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AdapterService.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AdapterService.java
@@ -84,4 +84,28 @@
* By default, the default constructor of the annotated class is used.
*/
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.
+ */
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ String removed() default "";
}
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AspectService.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AspectService.java
index fcffe88..12cf328 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AspectService.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/AspectService.java
@@ -87,6 +87,24 @@
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.
+ */
+ 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.
+ */
+ 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.
+ */
+ String removed() default "";
+
+ /**
* 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.
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 a2e7720..6e25fe4 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
@@ -75,7 +75,7 @@
private final static String A_RESOURCE_ADAPTER_SERVICE = "L" + ResourceAdapterService.class.getName().replace('.', '/') + ";";
private final static String A_FACTORYCONFIG_ADAPTER_SERVICE = "L" + FactoryConfigurationAdapterService.class.getName().replace('.', '/') + ";";
- private Reporter m_reporter;
+ private Logger m_logger;
private String m_className;
private String[] m_interfaces;
private boolean m_isField;
@@ -103,22 +103,13 @@
* Makes a new Collector for parsing a given class.
* @param reporter the object used to report logs.
*/
- public AnnotationCollector(Reporter reporter, MetaType metaType)
+ public AnnotationCollector(Logger reporter, MetaType metaType)
{
- m_reporter = reporter;
+ m_logger = reporter;
m_metaType = metaType;
}
/**
- * Returns the log reporter.
- * @return the log reporter.
- */
- public Reporter getReporter()
- {
- return m_reporter;
- }
-
- /**
* Parses the name of the class.
* @param access the class access
* @param name the class name (package are "/" separated).
@@ -127,7 +118,7 @@
public void classBegin(int access, String name)
{
m_className = name.replace('/', '.');
- m_reporter.trace("class name: " + m_className);
+ m_logger.debug("class name: %s", m_className);
}
/**
@@ -141,7 +132,7 @@
{
m_interfaces[i] = interfaces[i].replace('/', '.');
}
- m_reporter.trace("implements: %s", Arrays.toString(m_interfaces));
+ m_logger.debug("implements: %s", Arrays.toString(m_interfaces));
}
/**
@@ -150,7 +141,7 @@
@Override
public void method(int access, String name, String descriptor)
{
- m_reporter.trace("Parsed method %s, descriptor=%s", name, descriptor);
+ m_logger.debug("Parsed method %s, descriptor=%s", name, descriptor);
m_isField = false;
m_method = name;
m_descriptor = descriptor;
@@ -163,7 +154,7 @@
@Override
public void field(int access, String name, String descriptor)
{
- m_reporter.trace("Parsed field %s, descriptor=%s", name, descriptor);
+ m_logger.debug("Parsed field %s, descriptor=%s", name, descriptor);
m_isField = true;
m_field = name;
m_descriptor = descriptor;
@@ -175,7 +166,7 @@
@Override
public void annotation(Annotation annotation)
{
- m_reporter.trace("Parsed annotation: %s", annotation);
+ m_logger.debug("Parsed annotation: %s", annotation);
if (annotation.getName().equals(A_COMPONENT))
{
@@ -243,6 +234,47 @@
}
}
+ /**
+ * Finishes up the class parsing. This method must be called once the parseClassFileWithCollector method has returned.
+ * @return true if some annotations have been parsed, false if not.
+ */
+ public boolean finish()
+ {
+ if (m_writers.size() == 0)
+ {
+ return false;
+ }
+
+ // We must have at least a Service annotation.
+ checkServiceDeclared(EntryType.Component, EntryType.AspectService, EntryType.AdapterService,
+ EntryType.BundleAdapterService,
+ EntryType.ResourceAdapterService, EntryType.FactoryConfigurationAdapterService);
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("Parsed annotation for class ");
+ sb.append(m_className);
+ for (int i = m_writers.size() - 1; i >= 0; i--)
+ {
+ sb.append("\n\t").append(m_writers.get(i).toString());
+ }
+ m_logger.info(sb.toString());
+ return true;
+ }
+
+ /**
+ * Writes the generated component descriptor in the given print writer.
+ * The first line must be the service (@Service or AspectService).
+ * @param pw the writer where the component descriptor will be written.
+ */
+ public void writeTo(PrintWriter pw)
+ {
+ // The last element our our m_writers list contains either the Service, or the AspectService descriptor.
+ for (int i = m_writers.size() - 1; i >= 0; i--)
+ {
+ pw.println(m_writers.get(i).toString());
+ }
+ }
+
private void parseComponentAnnotation(Annotation annotation)
{
EntryWriter writer = new EntryWriter(EntryType.Component);
@@ -397,6 +429,9 @@
// pid attribute
writer.putString(annotation, EntryParam.pid, m_className);
+ // the method on which the annotation is applied
+ writer.put(EntryParam.updated, m_method);
+
// propagate attribute
writer.putString(annotation, EntryParam.propagate, null);
@@ -435,8 +470,8 @@
// Parse Aspect properties.
parseProperties(annotation, EntryParam.properties, writer);
- // Parse aspect impl field where to inject the original service.
- writer.putString(annotation, EntryParam.field, null);
+ // Parse field/added/changed/removed attributes
+ parseAspectOrAdapterCallbackMethods(annotation, writer);
// Parse service interface this aspect is applying to
Object service = annotation.get(EntryParam.service.toString());
@@ -466,6 +501,36 @@
writer.putString(annotation, EntryParam.factoryMethod, null);
}
+ private void parseAspectOrAdapterCallbackMethods(Annotation annotation, EntryWriter writer)
+ {
+ String field = annotation.get(EntryParam.field.toString());
+ String added = annotation.get(EntryParam.added.toString());
+ String changed = annotation.get(EntryParam.changed.toString());
+ String removed = annotation.get(EntryParam.removed.toString());
+
+ // "field" and "added/changed/removed" attributes can't be mixed
+ if (field != null && (added != null || changed != null || removed != null))
+ {
+ throw new IllegalStateException("Annotation " + annotation + "can't applied on " + m_className
+ + " can't mix \"field\" attribute with \"added/changed/removed\" attributes");
+ }
+
+ // changed/removed callbacks are allowed only if added callback is defined
+ if (field == null && added == null && (changed != null || removed != null))
+ {
+ throw new IllegalStateException("Annotation " + annotation + " applied on " + m_className
+ + " must define an \"added\" callback");
+ }
+
+ // Parse aspect impl field where to inject the original service.
+ writer.putString(annotation, EntryParam.field, null);
+
+ // Parse aspect impl callback methods.
+ writer.putString(annotation, EntryParam.added, null);
+ writer.putString(annotation, EntryParam.changed, null);
+ writer.putString(annotation, EntryParam.removed, null);
+ }
+
/**
* Parses an AspectService annotation.
* @param annotation
@@ -500,6 +565,9 @@
// Parse factoryMethod attribute
writer.putString(annotation, EntryParam.factoryMethod, null);
+
+ // Parse field/added/changed/removed attributes
+ parseAspectOrAdapterCallbackMethods(annotation, writer);
}
/**
@@ -758,7 +826,7 @@
m_metaType.add(ocd);
MetaType.Designate designate = new MetaType.Designate(pid, factory);
m_metaType.add(designate);
- m_reporter.warning("Parsed MetaType Properties from class " + m_className);
+ m_logger.info("Parsed MetaType Properties from class " + m_className);
}
}
@@ -834,56 +902,15 @@
/**
* 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 annotation 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
*/
@SuppressWarnings("unchecked")
- private <T> T get(Annotation properties, String name, T defaultValue)
+ private <T> T get(Annotation annotation, String name, T defaultValue)
{
- T value = (T) properties.get(name);
+ T value = (T) annotation.get(name);
return value != null ? value : defaultValue;
- }
-
- /**
- * Finishes up the class parsing. This method must be called once the parseClassFileWithCollector method has returned.
- * @return true if some annotations have been parsed, false if not.
- */
- public boolean finish()
- {
- if (m_writers.size() == 0)
- {
- return false;
- }
-
- // We must have at least a Service annotation.
- checkServiceDeclared(EntryType.Component, EntryType.AspectService, EntryType.AdapterService,
- EntryType.BundleAdapterService,
- EntryType.ResourceAdapterService, EntryType.FactoryConfigurationAdapterService);
-
- StringBuilder sb = new StringBuilder();
- sb.append("Parsed annotation for class ");
- sb.append(m_className);
- for (int i = m_writers.size() - 1; i >= 0; i--)
- {
- sb.append("\n\t").append(m_writers.get(i).toString());
- }
- m_reporter.warning(sb.toString());
- return true;
- }
-
- /**
- * Writes the generated component descriptor in the given print writer.
- * The first line must be the service (@Service or AspectService).
- * @param pw the writer where the component descriptor will be written.
- */
- public void writeTo(PrintWriter pw)
- {
- // The last element our our m_writers list contains either the Service, or the AspectService descriptor.
- for (int i = m_writers.size() - 1; i >= 0; i--)
- {
- pw.println(m_writers.get(i).toString());
- }
- }
-}
+ }
+}
\ No newline at end of file
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 0709918..88343aa 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
@@ -18,19 +18,27 @@
*/
package org.apache.felix.dm.annotation.plugin.bnd;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Iterator;
import java.util.Map;
import aQute.bnd.service.AnalyzerPlugin;
+import aQute.bnd.service.Plugin;
import aQute.lib.osgi.Analyzer;
import aQute.lib.osgi.Resource;
+import aQute.libg.reporter.Reporter;
/**
* This class is a BND plugin. It scans the target bundle and look for DependencyManager annotations.
* It can be directly used when using ant and can be referenced inside the ".bnd" descriptor, using
* the "-plugin" parameter.
*/
-public class AnnotationPlugin implements AnalyzerPlugin
+public class AnnotationPlugin implements AnalyzerPlugin, Plugin
{
+ private BndLogger m_logger;
+ private Reporter m_reporter;
+
/**
* This plugin is called after analysis of the JAR but before manifest
* generation. When some DM annotations are found, the plugin will add the corresponding
@@ -43,27 +51,85 @@
*/
public boolean analyzeJar(Analyzer analyzer) throws Exception
{
- // We'll do the actual parsing using a DescriptorGenerator object.
- DescriptorGenerator generator = new DescriptorGenerator(analyzer);
- if (generator.execute())
+ analyzer.setExceptions(true);
+ try {
+ // We'll do the actual parsing using a DescriptorGenerator object.
+ DescriptorGenerator generator = new DescriptorGenerator(analyzer, m_logger);
+
+ if (generator.execute())
+ {
+ // We have parsed some annotations: set the OSGi "DependencyManager-Component" header in the target bundle.
+ analyzer.setProperty("DependencyManager-Component", generator.getDescriptorPaths());
+
+ // And insert the generated descriptors into the target bundle.
+ Map<String, Resource> resources = generator.getDescriptors();
+ for (Map.Entry<String, Resource> entry : resources.entrySet())
+ {
+ 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);
+ }
+ }
+ }
+
+ catch (Throwable t)
{
- // We have parsed some annotations: set the OSGi "DependencyManager-Component" header in the target bundle.
- analyzer.setProperty("DependencyManager-Component", generator.getDescriptorPaths());
+ m_logger.error(parse(t));
+ }
- // And insert the generated descriptors into the target bundle.
- Map<String, Resource> resources = generator.getDescriptors();
- for (Map.Entry<String, Resource> entry : resources.entrySet())
+ // Collect all logs and write it into the analyzer.
+ m_logger.getLogs(analyzer);
+
+ // When some errors are present in the analyzer logs: it seems that the Bnd ANT task
+ // does not report it. So, to work around, we just log the errors ourself, and
+ // we throw an Error in case some errors are detected, in order to prevent the bnd ANT
+ // task from generating the target bundle.
+ if (analyzer.getWarnings().size() > 0)
+ {
+ for (Iterator<String> e = analyzer.getWarnings().iterator(); e.hasNext();)
{
- analyzer.getJar().putResource(entry.getKey(), entry.getValue());
- }
-
- // Inser the metatype resource, if any.
- Resource metaType = generator.getMetaTypeResource();
- if (metaType != null)
+ System.out.println(e.next());
+ }
+ analyzer.getWarnings().clear();
+ }
+
+ if (analyzer.getErrors().size() > 0)
+ {
+ for (Iterator<String> e = analyzer.getErrors().iterator(); e.hasNext();)
{
- analyzer.getJar().putResource("OSGI-INF/metatype/metatype.xml", metaType);
+ System.err.println(e.next());
}
+ analyzer.getErrors().clear();
+ throw new Error("DM Annotation plugin failure");
}
return false;
}
+
+ public void setProperties(Map<String, String> map)
+ {
+ String logLevel = map.get("log");
+ m_logger = new BndLogger(logLevel == null ? "error" : logLevel);
+ }
+
+ public void setReporter(Reporter reporter)
+ {
+ m_reporter = reporter;
+ }
+
+ /**
+ * 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());
+ }
}
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/BndLogger.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/BndLogger.java
new file mode 100644
index 0000000..2c868a8
--- /dev/null
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/BndLogger.java
@@ -0,0 +1,78 @@
+/*
+ * 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.plugin.bnd;
+
+import aQute.lib.osgi.Analyzer;
+import aQute.lib.osgi.Processor;
+
+public class BndLogger extends Logger
+{
+ private Processor m_processor = new Processor();
+
+ private final int m_level;
+
+ public BndLogger(String level)
+ {
+ m_level = parseLogLevel(level);
+ }
+
+ @Override
+ public void error(String msg, Object ... args)
+ {
+ m_processor.error(msg, args);
+ }
+
+ @Override
+ public void error(String msg, Throwable err, Object ... args)
+ {
+ m_processor.error(msg, err, args);
+ }
+
+ @Override
+ public void warn(String msg , Object ... args)
+ {
+ if (m_level >= WARN)
+ {
+ m_processor.warning(msg, args);
+ }
+ }
+
+ @Override
+ public void info(String msg, Object ... args)
+ {
+ if (m_level >= INFO)
+ {
+ m_processor.warning(msg, args);
+ }
+ }
+
+ @Override
+ public void debug(String msg, Object ... args)
+ {
+ if (m_level >= DEBUG)
+ {
+ m_processor.warning(msg, args);
+ }
+ }
+
+ public void getLogs(Analyzer to)
+ {
+ to.getInfo(m_processor, "DependencyManager: ");
+ }
+}
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 6b301cc..25c2be3 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
@@ -30,14 +30,13 @@
import aQute.lib.osgi.Analyzer;
import aQute.lib.osgi.Clazz;
import aQute.lib.osgi.EmbeddedResource;
-import aQute.lib.osgi.Processor;
import aQute.lib.osgi.Resource;
import aQute.lib.osgi.Clazz.QUERY;
/**
* This helper parses all classes which contain DM annotations, and generates the corresponding component descriptors.
*/
-public class DescriptorGenerator extends Processor
+public class DescriptorGenerator
{
/**
* This is the bnd analyzer used to lookup classes containing DM annotations.
@@ -57,13 +56,19 @@
private Resource m_metaTypeResource;
/**
+ * Object used to collect logs.
+ */
+ private final Logger m_logger;
+
+ /**
* Creates a new descriptor generator.
* @param analyzer The bnd analyzer used to lookup classes containing DM annotations.
+ * @param debug
*/
- public DescriptorGenerator(Analyzer analyzer)
+ public DescriptorGenerator(Analyzer analyzer, Logger logger)
{
- super(analyzer);
m_analyzer = analyzer;
+ m_logger = logger;
}
/**
@@ -71,64 +76,41 @@
* @return true if some annotations were successfully parsed, false if not. corresponding generated
* descriptors can then be retrieved by invoking the getDescriptors/getDescriptorPaths methods.
*/
- public boolean execute()
+ public boolean execute() throws Exception
{
boolean annotationsFound = false;
Clazz clazz = null;
- try
- {
- // Try to locate any classes in the wildcarded universe
- // that are annotated with the DependencyManager "Service" annotations.
- Collection<Clazz> expanded = m_analyzer.getClasses("",
- // Parse everything
- QUERY.NAMED.toString(), "*");
+ // Try to locate any classes in the wildcarded universe
+ // that are annotated with the DependencyManager "Service" annotations.
+ Collection<Clazz> expanded = m_analyzer.getClasses("",
+ // Parse everything
+ QUERY.NAMED.toString(), "*");
- // Create the object which will collect Config Admin MetaTypes.
- MetaType metaType = new MetaType();
+ // 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, metaType);
- c.parseClassFileWithCollector(reader);
- if (reader.finish())
- {
- // And store the generated component descriptors in our resource list.
- String name = c.getFQN();
- Resource resource = createComponentResource(reader);
- m_resources.put("OSGI-INF/dependencymanager/" + name, resource);
- 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)
+ for (Clazz c : expanded)
{
- StringBuilder sb = new StringBuilder();
- sb.append("Error while scanning annotations");
- if (clazz != null)
+ clazz = c;
+ // Let's parse all annotations from that class !
+ AnnotationCollector reader = new AnnotationCollector(m_logger, metaType);
+ c.parseClassFileWithCollector(reader);
+ if (reader.finish())
{
- sb.append(" from class " + clazz);
+ // And store the generated component descriptors in our resource list.
+ String name = c.getFQN();
+ Resource resource = createComponentResource(reader);
+ m_resources.put("META-INF/dependencymanager/" + name, resource);
+ annotationsFound = true;
}
- sb.append(": ");
- sb.append(parse(err));
- error(sb.toString());
- return false;
}
- finally
+ // If some Meta Types have been parsed, then creates the corresponding resource file.
+ if (metaType.getSize() > 0)
{
- // Collect all logs (warns/errors) from our processor and store them into the analyze.
- // Bnd will log them, if necessary.
- m_analyzer.getInfo(this, "DependencyManager: ");
- close();
+ m_metaTypeResource = createMetaTypeResource(metaType);
}
+ return annotationsFound;
}
/**
@@ -196,17 +178,5 @@
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());
- }
-}
+ }
+}
\ No newline at end of file
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/Logger.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/Logger.java
new file mode 100644
index 0000000..a421aab
--- /dev/null
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/Logger.java
@@ -0,0 +1,57 @@
+/*
+ * 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.plugin.bnd;
+
+public abstract class Logger
+{
+ protected final static int ERROR = 1;
+ protected final static int WARN = 2;
+ protected final static int INFO = 3;
+ protected final static int DEBUG = 4;
+
+ protected int parseLogLevel(String level)
+ {
+ if (level == null || level.regionMatches(true, 0, "err", 0, "err".length()))
+ {
+ return ERROR;
+ }
+ else if (level.regionMatches(true, 0, "warn", 0, "warn".length()))
+ {
+ return WARN;
+ }
+ else if (level.regionMatches(true, 0, "info", 0, "info".length()))
+ {
+ return INFO;
+ }
+ else if (level.regionMatches(true, 0, "debug", 0, "debug".length()))
+ {
+ return DEBUG;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid log level value: " + level + " (valid values are \"error\", \"warn\", \"debug\")");
+ }
+ }
+
+ public abstract void error(String msg, Object ... args);
+ public abstract void error(String msg, Throwable err, Object ... args);
+ public abstract void warn(String msg , Object ... args);
+ public abstract void info(String msg , Object ... args);
+ public abstract void debug(String msg, Object ... args);
+}
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/AnnotationMojo.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/AnnotationMojo.java
index f65d5ac..f524a86 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/AnnotationMojo.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/AnnotationMojo.java
@@ -19,7 +19,6 @@
package org.apache.felix.dm.annotation.plugin.mvn;
import java.io.File;
-import java.util.Iterator;
import java.util.Map;
import org.apache.felix.dm.annotation.plugin.bnd.DescriptorGenerator;
@@ -59,6 +58,13 @@
* @required
*/
private String m_artifactExtension;
+
+ /**
+ * If set, configures the log level.
+ *
+ * @parameter alias="log"
+ */
+ private String m_log;
/**
* Executes this mojo. We'll use the bnd library in order to scan classes from our target bundle.
@@ -80,7 +86,7 @@
analyzer.analyze();
// This helper class will parse classes using the analyzer we just created.
- DescriptorGenerator generator = new DescriptorGenerator(analyzer);
+ DescriptorGenerator generator = new DescriptorGenerator(analyzer, new MvnLogger(getLog(), m_log));
// Start scanning
if (generator.execute())
@@ -104,25 +110,6 @@
}
copy(jar, target);
}
-
- // Check if some errors have to be logged.
- if (analyzer.getErrors().size() != 0)
- {
- for (Iterator<String> e = analyzer.getErrors().iterator(); e.hasNext();)
- {
- getLog().error(e.next());
- }
- throw new MojoExecutionException("Errors while generating dm descriptors");
- }
-
- // Check if some warnings have to be logged.
- if (analyzer.getWarnings().size() != 0)
- {
- for (Iterator<String> e = analyzer.getWarnings().iterator(); e.hasNext();)
- {
- getLog().info(e.next());
- }
- }
}
catch (MojoExecutionException e)
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/MvnLogger.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/MvnLogger.java
new file mode 100644
index 0000000..a36d716
--- /dev/null
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/mvn/MvnLogger.java
@@ -0,0 +1,70 @@
+/*
+ * 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.plugin.mvn;
+
+import org.apache.felix.dm.annotation.plugin.bnd.Logger;
+import org.apache.maven.plugin.logging.Log;
+
+public class MvnLogger extends Logger
+{
+ private final Log m_log;
+ private final int m_level;
+
+ public MvnLogger(Log log, String level)
+ {
+ m_log = log;
+ m_level = parseLogLevel(level);
+ }
+
+ @Override
+ public void error(String msg, Object... args)
+ {
+ m_log.error("DependencyManager: " + String.format(msg, args));
+ }
+
+ @Override
+ public void error(String msg, Throwable err, Object... args)
+ {
+ m_log.error("DependencyManager: " + String.format(msg, args), err);
+ }
+
+ @Override
+ public void warn(String msg, Object... args)
+ {
+ m_log.warn("DependencyManager: " + String.format(msg, args));
+ }
+
+ @Override
+ public void info(String msg, Object... args)
+ {
+ if (m_level >= INFO)
+ {
+ m_log.info("DependencyManager: " + String.format(msg, args));
+ }
+ }
+
+ @Override
+ public void debug(String msg, Object... args)
+ {
+ if (m_level >= DEBUG)
+ {
+ m_log.info("DependencyManager: " + String.format(msg, args));
+ }
+ }
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
index 98bd244..04864c8 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
@@ -47,8 +47,40 @@
String[] provides = srvMeta.getStrings(Params.provides, null);
Dictionary<String, Object> adapterProperties = srvMeta.getDictionary(Params.properties, null);
Class<?> adapteeService = b.loadClass(srvMeta.getString(Params.adapteeService));
- String adapteeFilter = srvMeta.getString(Params.adapteeFilter, null);
- Component service = dm.createAdapterService(adapteeService, adapteeFilter);
+ String adapteeFilter = srvMeta.getString(Params.adapteeFilter, null);
+ String field = srvMeta.getString(Params.field, null);
+ String added = srvMeta.getString(Params.added, null);
+ String changed = srvMeta.getString(Params.changed, null);
+ String removed = srvMeta.getString(Params.removed, null);
+
+ if (field != null && (added != null || changed != null || removed != null))
+ {
+ throw new IllegalArgumentException("autoconfig field " + field + " cant be defined with both added/changed/removed calllbacks");
+ }
+ if (field == null && added == null && (changed != null || removed != null))
+ {
+ throw new IllegalArgumentException("missing added callback");
+ }
+
+ Component service;
+
+ if (field != null)
+ {
+ service = dm.createAdapterService(adapteeService, adapteeFilter, field);
+ }
+ else
+ {
+ if (added != null)
+ {
+ service = dm.createAdapterService(adapteeService, adapteeFilter, added, changed, removed);
+
+ }
+ else
+ {
+ service = dm.createAdapterService(adapteeService, adapteeFilter);
+ }
+ }
+
service.setInterface(provides, adapterProperties);
String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java
index 9c0c42a..4d3d507 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java
@@ -50,10 +50,44 @@
String implClassName = srvMeta.getString(Params.impl);
Object implClass = b.loadClass(implClassName);
String field = srvMeta.getString(Params.field, null);
- String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
- Component service =
- dm.createAspectService(serviceInterface, serviceFilter, ranking, field)
+ String added = srvMeta.getString(Params.added, null);
+ String changed = srvMeta.getString(Params.changed, null);
+ String removed = srvMeta.getString(Params.removed, null);
+
+ if (field != null && (added != null || changed != null || removed != null))
+ {
+ throw new IllegalArgumentException("autoconfig field " + field + " cant be defined with both added/changed/removed calllbacks");
+ }
+ if (field == null && added == null && (changed != null || removed != null))
+ {
+ throw new IllegalArgumentException("missing added callback");
+ }
+
+ Component service;
+ if (field != null)
+ {
+ service =
+ dm.createAspectService(serviceInterface, serviceFilter, ranking, field)
+ .setServiceProperties(aspectProperties);
+ }
+ else
+ {
+ if (added != null)
+ {
+ service =
+ dm.createAspectService(serviceInterface, serviceFilter, ranking, added, changed, removed)
.setServiceProperties(aspectProperties);
+ }
+ else
+ {
+ service =
+ dm.createAspectService(serviceInterface, serviceFilter, ranking)
+ .setServiceProperties(aspectProperties);
+ }
+
+ }
+
+ String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
if (factoryMethod == null)
{
service.setImplementation(implClass);
diff --git a/dependencymanager/samples.annotation/directives.bnd b/dependencymanager/samples.annotation/directives.bnd
index 510e3f5..dc246ef 100644
--- a/dependencymanager/samples.annotation/directives.bnd
+++ b/dependencymanager/samples.annotation/directives.bnd
@@ -2,4 +2,4 @@
Bundle-SymbolicName: org.apache.felix.dependencymanager.samples.annotation
Import-Package: *
Private-Package: org.apache.felix.dm.samples.annotation
--plugin org.apache.felix.dm.annotation.plugin.bnd.AnnotationPlugin
+-plugin org.apache.felix.dm.annotation.plugin.bnd.AnnotationPlugin;log=warn
diff --git a/dependencymanager/samples.annotation/pom.xml b/dependencymanager/samples.annotation/pom.xml
index c8be694..d6d4c68 100644
--- a/dependencymanager/samples.annotation/pom.xml
+++ b/dependencymanager/samples.annotation/pom.xml
@@ -66,6 +66,9 @@
<goals>
<goal>scan</goal>
</goals>
+ <configuration>
+ <log>warn</log>
+ </configuration>
</execution>
</executions>
</plugin>