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