Add annotation support in iPOJO. It is now possible to define component-type with Java 5 annotations.
(however, only the annotations project requires Java 5)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@565749 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/annotations/pom.xml b/ipojo/annotations/pom.xml
new file mode 100644
index 0000000..94867bb
--- /dev/null
+++ b/ipojo/annotations/pom.xml
@@ -0,0 +1,40 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>felix</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>../../pom/pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>org.apache.felix.ipojo.annotations</artifactId>
+ <packaging>bundle</packaging>
+ <version>0.7.3-SNAPSHOT</version>
+ <name>iPOJO Annotations</name>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>iPOJO Annotation</Bundle-Name>
+ <Bundle-Vendor>Clement ESCOFFIER</Bundle-Vendor>
+ <Bundle-Description> iPOJO Annotations </Bundle-Description>
+ <Export-Package>org.apache.felix.ipojo.annotations</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Attribute.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Attribute.java
new file mode 100644
index 0000000..482f693
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Attribute.java
@@ -0,0 +1,38 @@
+/*
+ * 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.ipojo.annotations;
+
+/**
+* This annotation declares an attribute.
+* This annotation must only be used in the attributes array of the Element annotation.
+* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+*/
+public @interface Attribute {
+
+ /**
+ * Set attribute name.
+ */
+ String name();
+
+ /**
+ * Set attribute value.
+ */
+ String value();
+
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Bind.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Bind.java
new file mode 100644
index 0000000..7e23a3c
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Bind.java
@@ -0,0 +1,61 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation declares a bind method.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target(ElementType.METHOD)
+public @interface Bind {
+
+ /**
+ * Set the dependency filter.
+ * Default : no filter
+ */
+ String filter() default "";
+
+ /**
+ * Set if the dependency is an aggregate dependency.
+ * Default : false
+ */
+ boolean aggregate() default false;
+
+ /**
+ * Set if the dependency is optional.
+ * Default : false
+ */
+ boolean optional() default false;
+
+ /**
+ * Set the required specification.
+ * Default : empty (try to discover)
+ */
+ String specification() default "";
+
+ /**
+ * Set the dependency id.
+ * Default : empty
+ */
+ String id() default "";
+
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Component.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Component.java
new file mode 100644
index 0000000..321a7b3
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Component.java
@@ -0,0 +1,61 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation declares a component.
+ * This annotation is mandatory to declares an iPOJO component.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target(ElementType.TYPE)
+public @interface Component {
+
+ /**
+ * Set if the component type is public.
+ * Default: false
+ */
+ boolean factory() default false;
+
+ /**
+ * Set the component type name.
+ * Default : implementation class name.
+ */
+ String name() default "";
+
+ /**
+ * Enable / Disable the architecture exposition.
+ * Default : false
+ */
+ boolean architecture() default false;
+
+ /**
+ * Set if the component is immediate.
+ * Default : false
+ */
+ boolean immediate() default false;
+
+ /**
+ * Set if the component must propagate received configuration to provided services.
+ * default: false
+ */
+ boolean propagation() default false;
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Element.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Element.java
new file mode 100644
index 0000000..904d5b9
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Element.java
@@ -0,0 +1,54 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+* This annotation declares a generic element.
+* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+*/
+@Target(ElementType.TYPE)
+public @interface Element {
+
+ /**
+ * Set element name.
+ */
+ String name();
+
+ /**
+ * Set the element namespace.
+ * Default : no namespace.
+ */
+ String namespace() default "";
+
+ /**
+ * Set element attributes (@Attribute).
+ * Default : no attributes.
+ */
+ Attribute[] attributes() default { };
+
+ /**
+ * Set element sub-elements (@SubElement).
+ * Default : no sub-element.
+ */
+ SubElement[] elements() default { };
+
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Invalidate.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Invalidate.java
new file mode 100644
index 0000000..72a7c6c
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Invalidate.java
@@ -0,0 +1,31 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation declares an invalidate callback.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target(ElementType.METHOD)
+public @interface Invalidate {
+
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Property.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Property.java
new file mode 100644
index 0000000..ac0c7dd
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Property.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation declares a component property.
+ * It can target both fields and methods.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target({ ElementType.FIELD, ElementType.METHOD })
+public @interface Property {
+
+ /**
+ * Set property name.
+ * Default : empty
+ */
+ String name() default "";
+
+ /**
+ * Set property value.
+ * Default : empty
+ */
+ String value() default "";
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Provides.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Provides.java
new file mode 100644
index 0000000..3ea29b6
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Provides.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+* This annotation declares that the component instances will provide a service.
+* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+*/
+@Target(ElementType.TYPE)
+public @interface Provides {
+
+ /**
+ * Set the provided specifications.
+ * Default : all implemented interfaces
+ */
+ String specification() default "";
+
+ /**
+ * Set the service object creation policy.
+ * Two value are possible: SINGLETON or FACTORY. FACTORY means OSGi Service Factory.
+ * Default : SINGLETON
+ */
+ String factory() default "SINGLETON";
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Requires.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Requires.java
new file mode 100644
index 0000000..146f239
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Requires.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation declares a service requirement.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target(ElementType.FIELD)
+public @interface Requires {
+
+ /**
+ * Set the LDAP filter of the dependency.
+ * Default : no filter
+ */
+ String filter() default "";
+
+ /**
+ * Set if the dependency is optional.
+ * Default : false
+ */
+ boolean optional() default false;
+
+
+ /**
+ * Set the dependency id.
+ * Default : empty
+ */
+ String id() default "";
+
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/ServiceProperty.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/ServiceProperty.java
new file mode 100644
index 0000000..462204d
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/ServiceProperty.java
@@ -0,0 +1,44 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation declares a service property.
+ * It can target both fields and methods.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target({ ElementType.FIELD, ElementType.METHOD })
+public @interface ServiceProperty {
+
+ /**
+ * Set the property name.
+ * Default : empty
+ */
+ String name() default "";
+
+ /**
+ * Set the property value.
+ * Default : empty
+ */
+ String value() default "";
+
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/SubElement.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/SubElement.java
new file mode 100644
index 0000000..a0d3179
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/SubElement.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ipojo.annotations;
+
+/**
+* This annotation declares a sub-attribute.
+* This annotation must only be used in the elements array of the Element annotation.
+* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+*/
+public @interface SubElement {
+
+ /**
+ * Set the sub-element name.
+ */
+ String name();
+
+ /**
+ * Set the sub-element namespace.
+ * Default : no namespace.
+ */
+ String namespace() default "";
+
+ /**
+ * Set the sub-element attributes (@Attribute).
+ * Default : no attributes.
+ */
+ Attribute[] attributes() default { };
+
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Unbind.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Unbind.java
new file mode 100644
index 0000000..73cd9fa
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Unbind.java
@@ -0,0 +1,62 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation declares an unbind method.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target(ElementType.METHOD)
+public @interface Unbind {
+
+ /**
+ * Set the dependency filter.
+ * Default : no filter
+ */
+ String filter() default "";
+
+ /**
+ * Set if the dependency is an aggregate dependency.
+ * Default : false
+ */
+ boolean aggregate() default false;
+
+
+ /**
+ * Set if the dependency is optional.
+ * Default : false
+ */
+ boolean optional() default false;
+
+ /**
+ * Set the required specification.
+ * Default : empty (try to discover).
+ */
+ String specification() default "";
+
+ /**
+ * Set the dependency id.
+ * Default : empty.
+ */
+ String id() default "";
+
+}
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Validate.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Validate.java
new file mode 100644
index 0000000..50e239f
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Validate.java
@@ -0,0 +1,31 @@
+/*
+ * 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.ipojo.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation declares a validate callback.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target(ElementType.METHOD)
+public @interface Validate {
+
+}
diff --git a/ipojo/manipulator/pom.xml b/ipojo/manipulator/pom.xml
index b2d308b..1d78e3c 100644
--- a/ipojo/manipulator/pom.xml
+++ b/ipojo/manipulator/pom.xml
@@ -48,7 +48,8 @@
<Bundle-Description> iPOJO Manipulator </Bundle-Description>
<Export-Package>org.apache.felix.ipojo.manipulator</Export-Package>
<Private-Package>
- org.apache.felix.ipojo.manipulation,
+ org.apache.felix.ipojo.manipulation,
+ org.apache.felix.ipojo.manipulation.annotations,
org.apache.felix.ipojo.xml.parser,
org.objectweb.asm,
org.objectweb.asm.commons,
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
index 6d0bf4c..2309f23 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
@@ -23,20 +23,19 @@
import java.util.List;
import java.util.Map;
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
/**
* Check that a POJO is already manipulated or not.
* Moreover it allows to get manipulation data about this class.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class ClassChecker implements ClassVisitor, Opcodes {
+public class ClassChecker extends EmptyVisitor implements ClassVisitor, Opcodes {
/**
* True if the class is already manipulated.
@@ -121,56 +120,6 @@
}
/**
- * Visit sources.
- * Do nothing
- * @param source : the name of the source file from which the class was compiled. May be null.
- @param debug : additional debug information to compute the relationship between source and compiled elements of the class. May be null.
- * @see org.objectweb.asm.ClassVisitor#visitSource(java.lang.String, java.lang.String)
- */
- public void visitSource(String source, String debug) { }
-
- /**
- * Visit an outer class.
- * @param owner - internal name of the enclosing class of the class.
- * @param name - the name of the method that contains the class, or null if the class is not enclosed in a method of its enclosing class.
- * @param desc - the descriptor of the method that contains the class, or null if the class is not enclosed in a method of its enclosing class.
- * @see org.objectweb.asm.ClassVisitor#visitOuterClass(java.lang.String, java.lang.String, java.lang.String)
- */
- public void visitOuterClass(String owner, String name, String desc) {
- }
-
- /**
- * Visit an annotation.
- * Do nothing.
- * @param desc - the class descriptor of the annotation class.
- * @param visible - true if the annotation is visible at runtime.
- * @return null.
- * @see org.objectweb.asm.ClassVisitor#visitAnnotation(java.lang.String, boolean)
- */
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- return null;
- }
-
- /**
- * Visit a non standard attribute of the class.
- * @param attr - an attribute.
- * @see org.objectweb.asm.ClassVisitor#visitAttribute(org.objectweb.asm.Attribute)
- */
- public void visitAttribute(Attribute attr) {
- }
-
- /**
- * Visit an inner class.
- * @param name - the internal name of an inner class (see getInternalName).
- * @param outerName - the internal name of the class to which the inner class belongs (see getInternalName). May be null for not member classes.
- * @param innerName - the (simple) name of the inner class inside its enclosing class. May be null for anonymous inner classes.
- * @param access - the access flags of the inner class as originally declared in the enclosing class.
- * @see org.objectweb.asm.ClassVisitor#visitInnerClass(java.lang.String,
- * java.lang.String, java.lang.String, int)
- */
- public void visitInnerClass(String name, String outerName, String innerName, int access) { }
-
- /**
* Visit a method.
* Update the method list (except if it init or clinit.
* @param access - the method's access flags (see Opcodes). This parameter also indicates if the method is synthetic and/or deprecated.
@@ -188,13 +137,7 @@
}
return null;
}
-
- /**
- * End of the class visit.
- * @see org.objectweb.asm.ClassVisitor#visitEnd()
- */
- public void visitEnd() { }
-
+
/**
* Get collected interfaces.
* @return the interfaces implemented by the component class.
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java
index deb4bc8..6930f2b 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java
@@ -129,7 +129,7 @@
/**
* Visit a field.
* Call the adapter generating getter and setter methods.
- * @param access : field acess.
+ * @param access : field access.
* @param name : field name
* @param desc : field descriptor
* @param signature : field signature
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java
new file mode 100644
index 0000000..4ecdc26
--- /dev/null
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/FieldCollector.java
@@ -0,0 +1,279 @@
+/*
+ * 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.ipojo.manipulation.annotations;
+
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Collect field annotations.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class FieldCollector extends EmptyVisitor implements FieldVisitor {
+
+ /**
+ * Collected element.
+ */
+ private Element m_element;
+
+ /**
+ * Field name.
+ */
+ private String m_field;
+
+ /**
+ * Constructor.
+ * @param fieldName : field name
+ * @param elem : element on which append the collected metadata.
+ */
+ public FieldCollector(String fieldName, Element elem) {
+ m_element = elem;
+ m_field = fieldName;
+ }
+
+ /**
+ * Visit annotations on the current field.
+ * @param arg0 : annotation name
+ * @param arg1 : is the annotation a runtime annotation.
+ * @return the annotation visitor visiting the annotation
+ * @see org.objectweb.asm.FieldVisitor#visitAnnotation(java.lang.String, boolean)
+ */
+ public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {
+ if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Requires;")) {
+ return new RequiresAnnotationParser(m_field);
+ }
+ if (arg0.equals("Lorg/apache/felix/ipojo/annotations/ServiceProperty;")) {
+ if (m_element.getElements("Provides", "").length == 0) {
+ System.err.println("The component does not provide services, skip ServiceProperty for " + m_field);
+ return null;
+ }
+ Element provides = m_element.getElements("Provides", "")[0];
+ return new PropertyAnnotationParser(provides, m_field);
+ }
+ if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Property;")) {
+ Element parent = null;
+ if (m_element.getElements("Properties", "").length == 0) {
+ parent = new Element("Properties", "");
+ m_element.addElement(parent);
+ }
+ parent = m_element.getElements("Properties", "")[0];
+ return new PropertyAnnotationParser(parent, m_field);
+ }
+ return null;
+
+ }
+
+ /**
+ * AnnotationVisitor parsing the @requires annotation.
+ */
+ private final class RequiresAnnotationParser extends EmptyVisitor implements AnnotationVisitor {
+
+ /**
+ * Dependency field.
+ */
+ private String m_field;
+
+ /**
+ * Dependency filter.
+ */
+ private String m_filter;
+
+ /**
+ * Is the dependency optional ?
+ */
+ private String m_optional;
+
+ /**
+ * Is the dependency aggregate ?
+ */
+ private String m_aggregate;
+
+ /**
+ * Dependency specification.
+ */
+ private String m_specification;
+
+ /**
+ * Dependency id.
+ */
+ private String m_id;
+
+ /**
+ * Constructor.
+ * @param name : field name.
+ */
+ private RequiresAnnotationParser(String name) {
+ m_field = name;
+ }
+
+ /**
+ * Visit one "simple" annotation.
+ * @param arg0 : annotation name
+ * @param arg1 : annotation value
+ * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
+ */
+ public void visit(String arg0, Object arg1) {
+ if (arg0.equals("filter")) {
+ m_filter = arg1.toString();
+ return;
+ }
+ if (arg0.equals("optional")) {
+ m_optional = arg1.toString();
+ return;
+ }
+ if (arg0.equals("specification")) {
+ m_specification = arg1.toString();
+ return;
+ }
+ if (arg0.equals("id")) {
+ m_id = arg1.toString();
+ return;
+ }
+ }
+
+ /**
+ * End of the annotation.
+ * Create a "requires" element
+ * @see org.objectweb.asm.AnnotationVisitor#visitEnd()
+ */
+ public void visitEnd() {
+ // Check if it is a full-determined requirement
+ Element req = null;
+ Element[] reqs = m_element.getElements("requires");
+ for (int i = 0; i < reqs.length; i++) {
+ if (reqs[i].containsAttribute("id") && (reqs[i].getAttribute("id").equals(m_id) || reqs[i].getAttribute("id").equals(m_field))) {
+ req = reqs[i];
+ break;
+ }
+ }
+ if (req == null) {
+ // Add the complete requires
+ req = new Element("requires", "");
+ }
+ req.addAttribute(new Attribute("field", m_field));
+ if (m_specification != null) {
+ req.addAttribute(new Attribute("interface", m_specification));
+ }
+ if (m_aggregate != null) {
+ req.addAttribute(new Attribute("aggregate", m_aggregate));
+ }
+ if (m_filter != null) {
+ req.addAttribute(new Attribute("filter", m_filter));
+ }
+ if (m_optional != null) {
+ req.addAttribute(new Attribute("optional", m_optional));
+ }
+ if (m_id != null) {
+ req.addAttribute(new Attribute("id", m_id));
+ }
+ m_element.addElement(req);
+ return;
+ }
+ }
+
+ /**
+ * Parse a @property annotation.
+ */
+ private final class PropertyAnnotationParser extends EmptyVisitor implements AnnotationVisitor {
+
+ /**
+ * Parent element (element on which append collected metadata).
+ */
+ private Element m_parent;
+
+ /**
+ * Field name.
+ */
+ private String m_field;
+
+ /**
+ * Property name.
+ */
+ private String m_name;
+
+ /**
+ * Property value.
+ */
+ private String m_value;
+
+
+ /**
+ * Constructor.
+ * @param parent : parent element.
+ * @param field : field name.
+ */
+ private PropertyAnnotationParser(Element parent, String field) {
+ m_parent = parent;
+ m_field = field;
+ }
+
+ /**
+ * Visit one "simple" annotation.
+ * @param arg0 : annotation name
+ * @param arg1 : annotation value
+ * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
+ */
+ public void visit(String arg0, Object arg1) {
+ if (arg0.equals("name")) {
+ m_name = arg1.toString();
+ return;
+ }
+ if (arg0.equals("value")) {
+ m_value = arg1.toString();
+ return;
+ }
+ }
+
+ /**
+ * End of the annotation.
+ * Create a "property" element
+ * @see org.objectweb.asm.AnnotationVisitor#visitEnd()
+ */
+ public void visitEnd() {
+ if (m_name == null) {
+ m_name = m_field;
+ }
+
+ Element[] props = m_parent.getElements("Property");
+ Element prop = null;
+ for (int i = 0; prop == null && i < props.length; i++) {
+ if (props[i].containsAttribute("name") && props[i].getAttribute("name").equals(m_name)) {
+ prop = props[i];
+ }
+ }
+
+ if (prop == null) {
+ prop = new Element("property", "");
+ m_parent.addElement(prop);
+ if (m_name != null) {
+ prop.addAttribute(new Attribute("name", m_name));
+ }
+ }
+
+ prop.addAttribute(new Attribute("field", m_field));
+ if (m_value != null) {
+ prop.addAttribute(new Attribute("value", m_value));
+ }
+
+ }
+ }
+}
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
new file mode 100644
index 0000000..c091cb1
--- /dev/null
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
@@ -0,0 +1,413 @@
+/*
+ * 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.ipojo.manipulation.annotations;
+
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Collect metadata from classes by parsing annotation.
+ * This class collects type (i.e.) annotations and create method & field collectors.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MetadataCollector extends EmptyVisitor implements Opcodes {
+
+ /**
+ * Class name.
+ */
+ private String m_className;
+
+ /**
+ * Root element of computed metadata.
+ */
+ private Element m_elem = new Element("component", "");
+
+ /**
+ * True if the visited class is a component type declaration (i.e. contains the @component annotation).
+ */
+ private boolean m_containsAnnotation = false;
+
+ public Element getElem() {
+ return m_elem;
+ }
+
+ public boolean isAnnotated() {
+ return m_containsAnnotation;
+ }
+
+ /**
+ * Start visiting a class.
+ * Initialize the getter/setter generator, add the _cm field, add the pojo interface.
+ * @param version : class version
+ * @param access : class access
+ * @param name : class name
+ * @param signature : class signature
+ * @param superName : class super class
+ * @param interfaces : implemented interfaces
+ * @see org.objectweb.asm.ClassAdapter#visit(int, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
+ */
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ m_className = name;
+ }
+
+
+ /**
+ * Visit class annotations.
+ * This method detects @component, @provides and @Element annotations.
+ * @param desc : annotation descriptor.
+ * @param visible : is the annotation visible at runtime.
+ * @return the annotation visitor.
+ * @see org.objectweb.asm.ClassAdapter#visitAnnotation(java.lang.String, boolean)
+ */
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ // @Component
+ if (desc.equals("Lorg/apache/felix/ipojo/annotations/Component;")) {
+ // It is a component
+ m_containsAnnotation = true;
+ m_elem.addAttribute(new Attribute("className", m_className.replace('/', '.')));
+ return new ComponentVisitor();
+ }
+
+ // @Provides
+ if (desc.equals("Lorg/apache/felix/ipojo/annotations/Provides;")) {
+ return new ProvidesVisitor();
+ }
+
+ //@Element
+ if (desc.equals("Lorg/apache/felix/ipojo/annotations/Element;")) {
+ return new ElementVisitor(m_elem);
+ }
+
+ return null;
+ }
+
+ /**
+ * Visit a field.
+ * Call the field collector visitor.
+ * @param access : field access.
+ * @param name : field name
+ * @param desc : field descriptor
+ * @param signature : field signature
+ * @param value : field value (static field only)
+ * @return the field visitor.
+ * @see org.objectweb.asm.ClassAdapter#visitField(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object)
+ */
+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
+ return new FieldCollector(name, m_elem);
+ }
+
+ /**
+ * Visit a method.
+ * Call the method collector visitor.
+ * @param access : method access
+ * @param name : method name
+ * @param desc : method descriptor
+ * @param signature : method signature
+ * @param exceptions : method exceptions
+ * @return the Method Visitor.
+ * @see org.objectweb.asm.ClassAdapter#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
+ */
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+ return new MethodCollector(name, m_elem);
+ }
+
+ /**
+ * Parse the @provides annotation.
+ */
+ private class ProvidesVisitor extends EmptyVisitor implements AnnotationVisitor {
+ /**
+ * Provides element.
+ */
+ Element m_prov = new Element("provides", "");
+
+ /**
+ * Visit @provides annotation attributes.
+ * @param arg0 : annotation attribute name
+ * @param arg1 : annotation attribute value
+ * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+ */
+ public void visit(String arg0, Object arg1) {
+ if (arg0.equals("specifications")) {
+ m_prov.addAttribute(new Attribute("interface", arg1.toString()));
+ }
+ if (arg0.equals("factory")) {
+ m_prov.addAttribute(new Attribute("factory", arg1.toString()));
+ }
+ }
+
+ /**
+ * End of the visit.
+ * Append to the parent element the computed "provides" element.
+ * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+ */
+ public void visitEnd() {
+ m_elem.addElement(m_prov);
+ }
+
+ }
+
+ /**
+ * Parse the @component annotation.
+ */
+ private class ComponentVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+ /**
+ * Factory attribute.
+ */
+ private String m_factory;
+
+ /**
+ * Is the component an immediate component?
+ */
+ private String m_immediate;
+
+ /**
+ * Component name (cannot be null).
+ */
+ private String m_name;
+
+ /**
+ * Does the component exposes its architecture?
+ */
+ private String m_architecture;
+
+ /**
+ * Does the component propagate configuration to provided services?
+ */
+ private String m_propagation;
+
+ /**
+ * Visit @component annotation attribute.
+ * @param arg0 : attribute name
+ * @param arg1 : attribute value
+ * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+ */
+ public void visit(String arg0, Object arg1) {
+ if (arg0.equals("factory")) {
+ m_factory = arg1.toString();
+ return;
+ }
+ if (arg0.equals("name")) {
+ m_name = arg1.toString();
+ return;
+ }
+ if (arg0.equals("immediate")) {
+ m_immediate = arg1.toString();
+ return;
+ }
+ if (arg0.equals("architecture")) {
+ m_architecture = arg1.toString();
+ return;
+ }
+ if (arg0.equals("propagation")) {
+ m_propagation = arg1.toString();
+ return;
+ }
+ }
+
+ /**
+ * End of the visit.
+ * Append to the "component" element computed attribute.
+ * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+ */
+ public void visitEnd() {
+ if (m_name == null) {
+ m_name = m_className.replace('/', '.');
+ }
+ m_elem.addAttribute(new Attribute("name", m_name));
+ if (m_factory == null) {
+ m_elem.addAttribute(new Attribute("factory", "false"));
+ } else {
+ m_elem.addAttribute(new Attribute("factory", m_factory));
+ }
+ if (m_architecture != null) {
+ m_elem.addAttribute(new Attribute("architecture", m_architecture));
+ }
+ if (m_immediate != null) {
+ m_elem.addAttribute(new Attribute("immediate", m_immediate));
+ }
+ if (m_propagation != null) {
+ Element props = new Element("properties", "");
+ props.addAttribute(new Attribute("propagation", m_propagation));
+ m_elem.addElement(props);
+ }
+ }
+ }
+
+ /**
+ * Parse the @Element & @SubElement annotations.
+ */
+ private class ElementVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+ /**
+ * Element name.
+ */
+ private String m_name;
+
+ /**
+ * Element namespace.
+ */
+ private String m_namespace;
+
+ /**
+ * Parent Element.
+ */
+ private Element m_parent;
+
+ /**
+ * Accumulator element to store temporary attributes and sub-elements.
+ */
+ private Element m_accu = new Element("accu", "");
+
+ /**
+ * Constructor.
+ * @param parent : parent element.
+ */
+ public ElementVisitor(Element parent) {
+ m_parent = parent;
+ }
+
+ /**
+ * Visit annotation attribute.
+ * @param arg0 : name of the attribute
+ * @param arg1 : value of the attribute
+ * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
+ */
+ public void visit(String arg0, Object arg1) {
+ if (arg0.equals("name")) {
+ m_name = arg1.toString();
+ }
+ if (arg0.equals("namespace")) {
+ m_namespace = arg1.toString();
+ }
+ }
+
+
+ /**
+ * Visit array annotation attribute (attributes & elements).
+ * @param arg0 : attribute name
+ * @return the annotation visitor which will visit the content of the array
+ * @see org.objectweb.asm.AnnotationVisitor#visitArray(java.lang.String)
+ */
+ public AnnotationVisitor visitArray(String arg0) {
+ if (arg0.equals("attributes")) {
+ return new EmptyVisitor() {
+ public AnnotationVisitor visitAnnotation(String arg0, String arg1) {
+ return new AttributeVisitor(m_accu);
+ }
+
+ };
+ }
+ if (arg0.equals("elements")) {
+ return new EmptyVisitor() {
+ public AnnotationVisitor visitAnnotation(String arg0, String arg1) {
+ return new ElementVisitor(m_accu);
+ }
+
+ };
+ }
+ return null;
+ }
+
+ /**
+ * End of the visit.
+ * Append computed element to the parent element.
+ * @see org.objectweb.asm.AnnotationVisitor#visitEnd()
+ */
+ public void visitEnd() {
+ Element elem = null;
+ if (m_namespace != null) {
+ elem = new Element(m_name, m_namespace);
+ } else {
+ elem = new Element(m_name, "");
+ }
+
+ Attribute[] atts = m_accu.getAttributes();
+ for (int i = 0; i < atts.length; i++) {
+ elem.addAttribute(atts[i]);
+ }
+
+ Element[] elems = m_accu.getElements();
+ for (int i = 0; i < elems.length; i++) {
+ elem.addElement(elems[i]);
+ }
+
+ m_parent.addElement(elem);
+ }
+
+ }
+
+ /**
+ * Parse an @attribute annotation.
+ */
+ private class AttributeVisitor extends EmptyVisitor implements AnnotationVisitor {
+ /**
+ * Parent element.
+ */
+ private Element m_parent;
+
+ /**
+ * Attribute name.
+ */
+ private String m_name;
+
+ /**
+ * Attribute value.
+ */
+ private String m_value;
+
+ /**
+ * Constructor.
+ * @param parent : parent element.
+ */
+ public AttributeVisitor(Element parent) {
+ m_parent = parent;
+ }
+
+ /**
+ * Visit attributes.
+ * @param arg0 : attribute name
+ * @param arg1 : attribute value
+ * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+ */
+ public void visit(String arg0, Object arg1) {
+ if (arg0.equals("name")) {
+ m_name = arg1.toString();
+ return;
+ }
+ if (arg0.equals("value")) {
+ m_value = arg1.toString();
+ }
+ }
+
+ /**
+ * End of the visit.
+ * Append this current attribute to the parent element.
+ * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+ */
+ public void visitEnd() {
+ m_parent.addAttribute(new Attribute(m_name, m_value));
+ }
+ }
+}
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java
new file mode 100644
index 0000000..582e5e6
--- /dev/null
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java
@@ -0,0 +1,356 @@
+/*
+ * 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.ipojo.manipulation.annotations;
+
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * This class collects method annotations, and give them to the metadata collector.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MethodCollector extends EmptyVisitor {
+
+ /**
+ * Parent element (component).
+ */
+ private Element m_element;
+
+ /**
+ * Method name.
+ */
+ private String m_name;
+
+ /**
+ * Constructor.
+ * @param name : name of the method.
+ * @param element : parent element.
+ */
+ public MethodCollector(String name, Element element) {
+ m_element = element;
+ m_name = name;
+ }
+
+ /**
+ * Visit method annotations.
+ * @param arg0 : annotation name.
+ * @param arg1 : is the annotation visible at runtime.
+ * @return the visitor paring the visited annotation.
+ * @see org.objectweb.asm.commons.EmptyVisitor#visitAnnotation(java.lang.String, boolean)
+ */
+ public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {
+ if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Property;")) {
+ return processProperty();
+ }
+ if (arg0.equals("Lorg/apache/felix/ipojo/annotations/ServiceProperty;")) {
+ return processServiceProperty();
+ }
+ if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Validate;")) {
+ return processValidate();
+ }
+ if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Invalidate;")) {
+ return processInvalidate();
+ }
+ if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Bind;")) {
+ return processBind("bind");
+ }
+ if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Unbind;")) {
+ return processBind("unbind");
+ }
+ return null;
+ }
+
+ /**
+ * Process @bind & @unbind.
+ * @param type : bind or unbind
+ * @return the visitor parsing @bind & @unbind annotations.
+ */
+ private AnnotationVisitor processBind(String type) {
+ return new BindAnnotationParser(m_name, type);
+ }
+
+ /**
+ * Process @validate annotation.
+ * @return null.
+ */
+ private AnnotationVisitor processValidate() {
+ Element cb = new Element("callback", "");
+ cb.addAttribute(new org.apache.felix.ipojo.metadata.Attribute("transition", "validate"));
+ cb.addAttribute(new org.apache.felix.ipojo.metadata.Attribute("method", m_name));
+ m_element.addElement(cb);
+ return null;
+ }
+
+ /**
+ * Process @invalidate annotation.
+ * @return null.
+ */
+ private AnnotationVisitor processInvalidate() {
+ Element cb = new Element("callback", "");
+ cb.addAttribute(new org.apache.felix.ipojo.metadata.Attribute("transition", "invalidate"));
+ cb.addAttribute(new org.apache.felix.ipojo.metadata.Attribute("method", m_name));
+ m_element.addElement(cb);
+ return null;
+ }
+
+ /**
+ * Process @serviceProperty annotation.
+ * @return the visitor parsing the visited annotation.
+ */
+ private AnnotationVisitor processServiceProperty() {
+ if (m_element.getElements("Provides", "").length == 0) {
+ System.err.println("the component does not provide services, skip ServiceProperty for " + m_name);
+ return null;
+ }
+ Element provides = m_element.getElements("Provides", "")[0];
+ return new PropertyAnnotationParser(provides, m_name);
+ }
+
+ /**
+ * Process @property annotation.
+ * @return the visitor parsing the visited annotation.
+ */
+ private AnnotationVisitor processProperty() {
+ if (m_element.getElements("Properties", "").length == 0) {
+ m_element.addElement(new Element("Properties", ""));
+ }
+ Element props = m_element.getElements("Properties", "")[0];
+ return new PropertyAnnotationParser(props, m_name);
+ }
+
+ /**
+ * Parse @bind & @unbind annotations.
+ */
+ private final class BindAnnotationParser extends EmptyVisitor implements AnnotationVisitor {
+
+ /**
+ * Method name.
+ */
+ private String m_name;
+
+ /**
+ * Requirement filter.
+ */
+ private String m_filter;
+
+ /**
+ * Is the requirement optional?
+ */
+ private String m_optional;
+
+ /**
+ * Is the requirement aggregate?
+ */
+ private String m_aggregate;
+
+ /**
+ * Required specification.
+ */
+ private String m_specification;
+
+ /**
+ * Requirement id.
+ */
+ private String m_id;
+
+ /**
+ * Bind or Unbind method?
+ */
+ private String m_type;
+
+ /**
+ * Constructor.
+ * @param bind : method name.
+ * @param type : is the callback a bind or an unbind method.
+ */
+ private BindAnnotationParser(String bind, String type) {
+ m_name = bind;
+ m_type = type;
+ }
+
+ /**
+ * Visit annotation attribute.
+ * @param arg0 : annotation name
+ * @param arg1 : annotation value
+ * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+ */
+ public void visit(String arg0, Object arg1) {
+ if (arg0.equals("filter")) {
+ m_filter = arg1.toString();
+ return;
+ }
+ if (arg0.equals("optional")) {
+ m_optional = arg1.toString();
+ return;
+ }
+ if (arg0.equals("aggregate")) {
+ m_aggregate = arg1.toString();
+ return;
+ }
+ if (arg0.equals("specification")) {
+ m_specification = arg1.toString();
+ return;
+ }
+ if (arg0.equals("id")) {
+ m_id = arg1.toString();
+ return;
+ }
+ }
+
+ /**
+ * End of the visit.
+ * Create or append the requirement info to a created or already existing "requires" element.
+ * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+ */
+ public void visitEnd() {
+ if (m_id == null) {
+ if (m_name.startsWith("bind")) {
+ m_id = m_name.substring("bind".length());
+ } else if (m_name.startsWith("unbind")) {
+ m_id = m_name.substring("unbind".length());
+ } else {
+ System.err.println("Cannot determine the id of the bind method : " + m_name);
+ return;
+ }
+ }
+ // Check if it is a full-determined requirement
+ Element req = null;
+ Element[] reqs = m_element.getElements("requires");
+ for (int i = 0; i < reqs.length; i++) {
+ if (reqs[i].containsAttribute("id") && reqs[i].getAttribute("id").equals(m_id)) {
+ req = reqs[i];
+ break;
+ }
+ if (reqs[i].containsAttribute("field") && reqs[i].getAttribute("field").equals(m_id)) {
+ req = reqs[i];
+ break;
+ }
+ }
+ if (req == null) {
+ // Add the complete requires
+ req = new Element("requires", "");
+ if (m_specification != null) {
+ req.addAttribute(new Attribute("interface", m_specification));
+ }
+ if (m_aggregate != null) {
+ req.addAttribute(new Attribute("aggregate", m_aggregate));
+ }
+ if (m_filter != null) {
+ req.addAttribute(new Attribute("filter", m_filter));
+ }
+ if (m_optional != null) {
+ req.addAttribute(new Attribute("optional", m_optional));
+ }
+ if (m_id != null) {
+ req.addAttribute(new Attribute("id", m_id));
+ }
+ }
+ Element method = new Element("callback", "");
+ method.addAttribute(new Attribute("method", m_name));
+ method.addAttribute(new Attribute("type", m_type));
+ req.addElement(method);
+ m_element.addElement(req);
+ return;
+ }
+ }
+
+ private final class PropertyAnnotationParser extends EmptyVisitor implements AnnotationVisitor {
+
+ /**
+ * Parent element.
+ */
+ private Element m_parent;
+
+ /**
+ * Attached method.
+ */
+ private String m_method;
+
+ /**
+ * Property name.
+ */
+ private String m_name;
+
+ /**
+ * Property value.
+ */
+ private String m_value;
+
+ /**
+ * Constructor.
+ * @param parent : parent element.
+ * @param method : attached method.
+ */
+ private PropertyAnnotationParser(Element parent, String method) {
+ m_parent = parent;
+ m_method = method;
+ }
+
+ /**
+ * Visit annotation attributes.
+ * @param arg0 : annotation name
+ * @param arg1 : annotation value
+ * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+ */
+ public void visit(String arg0, Object arg1) {
+ if (arg0.equals("name")) {
+ m_name = arg1.toString();
+ return;
+ }
+ if (arg0.equals("value")) {
+ m_value = arg1.toString();
+ return;
+ }
+ }
+
+ /**
+ * End of the visit.
+ * Append the computed element to the parent element.
+ * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+ */
+ public void visitEnd() {
+ if (m_name == null && m_method.startsWith("set")) {
+ m_name = m_method.substring("set".length());
+ }
+ Element[] props = m_parent.getElements("Property");
+ Element prop = null;
+ for (int i = 0; prop == null && i < props.length; i++) {
+ if (props[i].containsAttribute("name") && props[i].getAttribute("name").equals(m_name)) {
+ prop = props[i];
+ }
+ }
+
+ if (prop == null) {
+ prop = new Element("property", "");
+ m_parent.addElement(prop);
+ if (m_name != null) {
+ prop.addAttribute(new Attribute("name", m_name));
+ }
+ }
+
+ prop.addAttribute(new Attribute("method", m_method));
+ if (m_value != null) {
+ prop.addAttribute(new Attribute("value", m_value));
+ }
+
+ }
+ }
+}
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
index 6c4b43b..066829f 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
@@ -39,13 +39,14 @@
import java.util.jar.Manifest;
import org.apache.felix.ipojo.manipulation.Manipulator;
+import org.apache.felix.ipojo.manipulation.annotations.MetadataCollector;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.xml.parser.ParseException;
import org.apache.felix.ipojo.xml.parser.XMLMetadataParser;
+import org.objectweb.asm.ClassReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.XMLReaderFactory;
/**
* Pojoization allows creating an iPOJO bundle from a "normal" bundle.
@@ -61,7 +62,7 @@
/**
* Metadata (in internal format).
*/
- private Element[] m_metadata;
+ private Element[] m_metadata = new Element[0];
/**
* Errors which occur during the manipulation.
@@ -114,18 +115,28 @@
* @param metadataFile : iPOJO metadata file (XML).
*/
public void pojoization(File in, File out, File metadataFile) {
- // Get the metadata.xml location
- String path = metadataFile.getAbsolutePath();
- if (!path.startsWith("/")) {
- path = "/" + path;
+ // Get the metadata.xml location if not null
+ if (metadataFile != null) {
+ String path = metadataFile.getAbsolutePath();
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+ m_metadata = parseXMLMetadata(path);
}
- m_metadata = parseXMLMetadata(path);
+
+ JarFile inputJar;
+ try {
+ inputJar = new JarFile(in);
+ } catch (IOException e) {
+ error("The input file " + in.getAbsolutePath() + " is not a Jar file");
+ return;
+ }
// Get the list of declared component
m_components = getDeclaredComponents(m_metadata);
// Start the manipulation
- manipulation(in, out);
+ manipulation(inputJar, out);
// Check that all declared components are manipulated
for (int i = 0; i < m_components.size(); i++) {
@@ -137,21 +148,47 @@
}
/**
+ * Parse the content of the input Jar file to detect annotated classes.
+ * @param inC : the class to inspect.
+ */
+ private void computeAnnotations(byte[] inC) {
+ ClassReader cr = new ClassReader(inC);
+ MetadataCollector xml = new MetadataCollector();
+ cr.accept(xml, 0);
+ if (xml.isAnnotated()) {
+ boolean toskip = false;
+ for (int i = 0; !toskip && i < m_metadata.length; i++) {
+ if (m_metadata[i].containsAttribute("name")
+ && m_metadata[i].getAttribute("name").equalsIgnoreCase(xml.getElem().getAttribute("name"))) {
+ toskip = true;
+ warn("The component " + xml.getElem().getAttribute("name") + " is overriden by the metadata file");
+ }
+ }
+ if (!toskip) {
+ if (m_metadata != null || m_metadata.length != 0) {
+ Element[] newElementsList = new Element[m_metadata.length + 1];
+ System.arraycopy(m_metadata, 0, newElementsList, 0, m_metadata.length);
+ newElementsList[m_metadata.length] = xml.getElem();
+ m_metadata = newElementsList;
+ } else {
+ m_metadata = new Element[] { xml.getElem() };
+ }
+ String name = m_metadata[m_metadata.length - 1].getAttribute("classname");
+ name = name.replace('.', '/');
+ name += ".class";
+ m_components.add(new ComponentInfo(name, m_metadata[m_metadata.length - 1]));
+ }
+ }
+ }
+
+ /**
* Manipulate the Bundle.
- * @param in : original bundle
+ * @param inputJar : original bundle (JarFile)
* @param out : final bundle
*/
- private void manipulation(File in, File out) {
- // Get a jar file from the given file
- JarFile inputJar = null;
- try {
- inputJar = new JarFile(in);
- } catch (IOException e) {
- error("The input file is not a JarFile : " + in.getAbsolutePath());
- return;
- }
-
+ private void manipulation(JarFile inputJar, File out) {
manipulateComponents(inputJar); // Manipulate classes
+ m_referredPackages = getReferredPackages();
Manifest mf = doManifest(inputJar); // Compute the manifest
// Create a new Jar file
@@ -161,7 +198,7 @@
fos = new FileOutputStream(out);
jos = new JarOutputStream(fos, mf);
} catch (FileNotFoundException e1) {
- error("Cannot manipulate the Jar file : the file " + out.getAbsolutePath() + " not found");
+ error("Cannot manipulate the Jar file : the output file " + out.getAbsolutePath() + " is not found");
return;
} catch (IOException e) {
error("Cannot manipulate the Jar file : cannot access to " + out.getAbsolutePath());
@@ -235,12 +272,30 @@
Enumeration entries = inputJar.entries();
while (entries.hasMoreElements()) {
JarEntry curEntry = (JarEntry) entries.nextElement();
- // Check if we need to manipulate the class
- for (int i = 0; i < m_components.size(); i++) {
- ComponentInfo ci = (ComponentInfo) m_components.get(i);
- if (ci.m_classname.equals(curEntry.getName())) {
- byte[] outClazz = manipulateComponent(inputJar, curEntry, ci);
- m_classes.put(curEntry.getName(), outClazz);
+ if (curEntry.getName().endsWith(".class")) {
+ try {
+ InputStream currIn = inputJar.getInputStream(curEntry);
+ byte[] in = new byte[0];
+ int c;
+ while ((c = currIn.read()) >= 0) {
+ byte[] in2 = new byte[in.length + 1];
+ System.arraycopy(in, 0, in2, 0, in.length);
+ in2[in.length] = (byte) c;
+ in = in2;
+ }
+ currIn.close();
+ computeAnnotations(in);
+ // Check if we need to manipulate the class
+ for (int i = 0; i < m_components.size(); i++) {
+ ComponentInfo ci = (ComponentInfo) m_components.get(i);
+ if (ci.m_classname.equals(curEntry.getName())) {
+ byte[] outClazz = manipulateComponent(in, curEntry, ci);
+ m_classes.put(curEntry.getName(), outClazz);
+ }
+ }
+ } catch (IOException e) {
+ error("Cannot read the class : " + curEntry.getName());
+ return;
}
}
}
@@ -268,24 +323,14 @@
/**
* Manipulate a component class.
- * @param inputJar : input bundle
+ * @param in : the byte array of the class to manipulate
* @param je : Jar entry of the classes
* @param ci : attached component info (containing metadata and manipulation metadata)
* @return the generated class (byte array)
*/
- private byte[] manipulateComponent(JarFile inputJar, JarEntry je, ComponentInfo ci) {
+ private byte[] manipulateComponent(byte[] in, JarEntry je, ComponentInfo ci) {
Manipulator man = new Manipulator();
try {
- InputStream currIn = inputJar.getInputStream(je);
- byte[] in = new byte[0];
- int c;
- while ((c = currIn.read()) >= 0) {
- byte[] in2 = new byte[in.length + 1];
- System.arraycopy(in, 0, in2, 0, in.length);
- in2[in.length] = (byte) c;
- in = in2;
- }
- currIn.close();
byte[] out = man.manipulate(in); // iPOJO manipulation
// Insert information to metadata
ci.m_componentMetadata.addElement(man.getManipulationMetadata());
@@ -529,18 +574,17 @@
try {
url = metadata.toURL();
if (url == null) {
- error("Cannot find the metadata file : " + path);
- return null;
+ warn("Cannot find the metadata file : " + path);
+ return new Element[0];
}
- InputStream stream = url.openStream();
- XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
+ InputStream stream = url.openStream();
+ XMLReader parser = (XMLReader) Class.forName("org.apache.xerces.parsers.SAXParser").newInstance();
XMLMetadataParser handler = new XMLMetadataParser();
parser.setContentHandler(handler);
InputSource is = new InputSource(stream);
parser.parse(is);
meta = handler.getMetadata();
- m_referredPackages = handler.getReferredPackages();
stream.close();
} catch (MalformedURLException e) {
@@ -555,6 +599,15 @@
} catch (SAXException e) {
error("Parsing Error when parsing (Sax Error) the XML file " + path + " : " + e.getMessage());
return null;
+ } catch (InstantiationException e) {
+ error("Cannot instantiate the SAX parser for the XML file " + path + " : " + e.getMessage());
+ return null;
+ } catch (IllegalAccessException e) {
+ error("Cannot instantiate the SAX parser (IllegalAccess) for the XML file " + path + " : " + e.getMessage());
+ return null;
+ } catch (ClassNotFoundException e) {
+ error("Cannot load the Sax Parser : " + e.getMessage());
+ return null;
}
if (meta == null || meta.length == 0) {
@@ -563,6 +616,29 @@
return meta;
}
+
+ /**
+ * Get packages referenced by composite.
+ *
+ * @return the list of referenced packages.
+ */
+ private List getReferredPackages() {
+ List referred = new ArrayList();
+ for (int i = 0; i < m_metadata.length; i++) {
+ if (m_metadata[i].getName().equalsIgnoreCase("composite")) {
+ for (int j = 0; j < m_metadata[i].getElements().length; j++) {
+ if (m_metadata[i].getElements()[j].containsAttribute("specification")) {
+ String p = m_metadata[i].getElements()[j].getAttribute("specification");
+ int last = p.lastIndexOf('.');
+ if (last != -1) {
+ referred.add(p.substring(0, last));
+ }
+ }
+ }
+ }
+ }
+ return referred;
+ }
/**
* Generate manipulation metadata.
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/xml/parser/XMLMetadataParser.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/xml/parser/XMLMetadataParser.java
index 95899de..04d7a3f 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/xml/parser/XMLMetadataParser.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/xml/parser/XMLMetadataParser.java
@@ -18,9 +18,6 @@
*/
package org.apache.felix.ipojo.xml.parser;
-import java.util.ArrayList;
-import java.util.List;
-
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
import org.xml.sax.Attributes;
@@ -64,28 +61,6 @@
}
/**
- * Get packages referenced by composite.
- *
- * @return the list of referenced packages.
- */
- public List getReferredPackages() {
- List referred = new ArrayList();
- Element[] compo = m_elements[0].getElements("Composite");
- for (int i = 0; i < compo.length; i++) {
- for (int j = 0; j < compo[i].getElements().length; j++) {
- if (compo[i].getElements()[j].containsAttribute("specification")) {
- String p = compo[i].getElements()[j].getAttribute("specification");
- int last = p.lastIndexOf('.');
- if (last != -1) {
- referred.add(p.substring(0, last));
- }
- }
- }
- }
- return referred;
- }
-
- /**
* Get parsed metadata.
* The document must be parsed before calling this method.
* @return : all the metadata.
diff --git a/ipojo/metadata/pom.xml b/ipojo/metadata/pom.xml
index 56f4c5e..5b40d7e 100644
--- a/ipojo/metadata/pom.xml
+++ b/ipojo/metadata/pom.xml
@@ -19,7 +19,7 @@
<extensions>true</extensions>
<configuration>
<instructions>
- <Bundle-Name>iPOJO Manipulator</Bundle-Name>
+ <Bundle-Name>iPOJO Metadata</Bundle-Name>
<Bundle-Vendor>Clement ESCOFFIER</Bundle-Vendor>
<Bundle-Description> iPOJO Metadata </Bundle-Description>
<Export-Package>org.apache.felix.ipojo.metadata</Export-Package>
diff --git a/ipojo/plugin/pom.xml b/ipojo/plugin/pom.xml
index 1c21b09..6e1579f 100644
--- a/ipojo/plugin/pom.xml
+++ b/ipojo/plugin/pom.xml
@@ -32,11 +32,6 @@
<version>2.0</version>
</dependency>
<dependency>
- <groupId>asm</groupId>
- <artifactId>asm</artifactId>
- <version>3.0</version>
- </dependency>
- <dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.4.0</version>
diff --git a/ipojo/plugin/src/main/java/org/apache/felix/ipojo/plugin/ManipulatorMojo.java b/ipojo/plugin/src/main/java/org/apache/felix/ipojo/plugin/ManipulatorMojo.java
index c49c454..1f69a5e 100644
--- a/ipojo/plugin/src/main/java/org/apache/felix/ipojo/plugin/ManipulatorMojo.java
+++ b/ipojo/plugin/src/main/java/org/apache/felix/ipojo/plugin/ManipulatorMojo.java
@@ -80,7 +80,8 @@
File meta = new File(m_outputDirectory + "/" + m_metadata);
getLog().info("Metadata File : " + meta.getAbsolutePath());
if (!meta.exists()) {
- throw new MojoExecutionException("the specified metadata file does not exists");
+ getLog().info("No metadata file found - try to use only annotations");
+ meta = null;
}
// Get input bundle