FELIX-4112 Add meta-annotations for handler description
* @HandlerBinding can be used to declare an annotation as a handler
annotation (will produce Elements in the metadata structure). The
supporting annotation type do not have to be in a package containing
'handler' or 'ipojo'
* @Ignore can be used to ignore an annotation that would be (otherwise)
mapped to a custom handler annotation (because it contains 'handler'
or 'ipojo' in its name)
* Unified support for @Stereotype, @HandlerBinding and @Ignore
* Merged BindingRegistry and AnnotationBindingRegistry into 1 entity
** Implementation is split into 3 delegating registries for better
separation of concerns
* Module DSL improved to support @Stereotype, @HandlerBinding and
@Ignore registration
* Added annotations javadoc
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1507289 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/HandlerBinding.java b/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/HandlerBinding.java
new file mode 100644
index 0000000..f18f4c4
--- /dev/null
+++ b/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/HandlerBinding.java
@@ -0,0 +1,85 @@
+/*
+ * 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.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A @{@link HandlerBinding} bind its annotated type to a given handler.
+ *
+ * The handler name is specified as parameter using the {@literal 'namespace:name'} format (qualified name).
+ *
+ * <pre>
+ * // Namespace and name will be inferred from the annotation's package name.
+ * @HandlerBinding()
+ * public @interface Foo {}
+ *
+ * // No namespace declared, default will be used ('org.apache.felix.ipojo')
+ * @HandlerBinding("foo")
+ * public @interface Foo {}
+ *
+ * // Namespace will be 'com.acme' and name: 'foo'
+ * @HandlerBinding("com.acme:foo")
+ * public @interface Foo {}
+ *
+ * // Provided namespace and value (for the name) will be used
+ * @HandlerBinding(namespace = "com.acme", value = "foo")
+ * public @interface Foo {}
+ * </pre>
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target(ElementType.ANNOTATION_TYPE)
+@Retention(RetentionPolicy.CLASS)
+public @interface HandlerBinding {
+ String DEFAULT = "#";
+
+ /**
+ * Defines the handler's namespace. Must be used in correlation with the {@literal value} attribute.
+ * <pre>
+ * @HandlerBinding(namespace = "com.acme", value = "foo")
+ * public @interface Foo {}
+ * </pre>
+ */
+ String namespace() default DEFAULT;
+
+ /**
+ * When used <b>without</b> the {@literal namespace} attribute, defines both the namespace + name
+ * of a handler in a short notation (if no namespace can be found in the parameter - no ':' separator - fallback
+ * on iPOJO's default namespace):
+ *
+ * <pre>
+ * @HandlerBinding("com.acme:foo")
+ * public @interface Foo {}
+ * </pre>
+ *
+ * When used <b>with</b> the {@literal namespace} attribute, holds the name of the handler (without
+ * its namespace part):
+ *
+ * <pre>
+ * @HandlerBinding(namesapce = "com.acme", value = "foo")
+ * public @interface Foo {}
+ * </pre>
+ */
+ String value() default DEFAULT;
+}
diff --git a/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/Ignore.java b/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/Ignore.java
new file mode 100644
index 0000000..ceb4171
--- /dev/null
+++ b/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/Ignore.java
@@ -0,0 +1,42 @@
+/*
+ * 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.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A @{@link Ignore} annotation mark its annotated type to be ignored by the iPOJO manipulator.
+ * This is handy when the annotation could be recognized as a "custom annotation handler" (contains {@literal ".ipojo."}
+ * or {@literal ".handler."} in its package name) but in fact is not a handler annotation at all.
+ *
+ * <pre>
+ * package com.acme.ipojo.handler;
+ * @Ignore
+ * public @interface Foo {}
+ * </pre>
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target(ElementType.ANNOTATION_TYPE)
+@Retention(RetentionPolicy.CLASS)
+public @interface Ignore {}
diff --git a/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/Stereotype.java b/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/Stereotype.java
index e4cb647..efb8369 100644
--- a/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/Stereotype.java
+++ b/ipojo/manipulator/annotations/src/main/java/org/apache/felix/ipojo/annotations/Stereotype.java
@@ -24,7 +24,46 @@
import java.lang.annotation.Target;
/**
- * Mark the annotated annotation type to be a marker annotation dedicated to an iPOJO handler.
+ * In many systems, use of architectural patterns produces a set of recurring roles. A stereotype allows a
+ * framework developer to identify such a role and declare some common metadata for objects with that role
+ * in a central place.
+ *
+ * A stereotype is an annotation, annotated with {@literal @Stereotype}, that captures several other annotations.
+ *
+ * For example, the following stereotype defines a @PseudoSingletonComponent annotation, that will act,
+ * when applied on a component, just like if @Component and @Instantiate where directly applied on the target component.
+ * <pre>
+ *
+ * @Component
+ * @Instantiate
+ * @Stereotype
+ * @Target(TYPE)
+ * @Retention(CLASS)
+ * public @interface PseudoSingletonComponent {}
+ *
+ * </pre>
+ *
+ * Usage:
+ * <pre>
+ *
+ * @PseudoSingletonComponent
+ * public class HelloWorldComponent {
+ * // ...
+ * }
+ *
+ * </pre>
+ *
+ * Equivalent to:
+ * <pre>
+ *
+ * @Component
+ * @Instantiate
+ * public class HelloWorldComponent {
+ * // ...
+ * }
+ *
+ * </pre>
+ *
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
@Target(ElementType.ANNOTATION_TYPE)
diff --git a/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/HandlerBindingTestComponent.java b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/HandlerBindingTestComponent.java
new file mode 100644
index 0000000..85e7c7b
--- /dev/null
+++ b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/HandlerBindingTestComponent.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.runtime.core.components;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Instantiate;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.runtime.core.handlers.Foo;
+import org.apache.felix.ipojo.runtime.core.handlers.IgnoredFoo;
+import org.apache.felix.ipojo.runtime.core.services.HandlerBindingTestService;
+
+/**
+ * User: guillaume
+ * Date: 24/07/13
+ * Time: 12:31
+ */
+@Component
+@Provides
+@Instantiate
+public class HandlerBindingTestComponent implements HandlerBindingTestService {
+
+ @Foo("Bonjour")
+ private String greeting;
+
+ @Foo("Welcome")
+ private String welcome;
+
+ @IgnoredFoo("Ignored")
+ private String ignored;
+
+ @Override
+ public String get(final String name) {
+ if ("greeting".equals(name)) {
+ return greeting;
+ }
+ if ("welcome".equals(name)) {
+ return welcome;
+ }
+ if ("ignored".equals(name)) {
+ return ignored;
+ }
+ throw new IllegalArgumentException(name + " is not valid");
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/handlers/Foo.java
similarity index 63%
copy from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
copy to ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/handlers/Foo.java
index 1748cfc..79e93d7 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
+++ b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/handlers/Foo.java
@@ -17,15 +17,23 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.runtime.core.handlers;
-import org.objectweb.asm.AnnotationVisitor;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.felix.ipojo.annotations.HandlerBinding;
/**
-* User: guillaume
-* Date: 30/05/13
-* Time: 17:23
-*/
-public interface Replay {
- void accept(AnnotationVisitor visitor);
+ * User: guillaume
+ * Date: 24/07/13
+ * Time: 12:10
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.CLASS)
+@HandlerBinding("com.acme:foo")
+public @interface Foo {
+ String value();
}
diff --git a/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/handlers/FooHandler.java b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/handlers/FooHandler.java
new file mode 100644
index 0000000..cc86c67
--- /dev/null
+++ b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/handlers/FooHandler.java
@@ -0,0 +1,84 @@
+/*
+ * 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.runtime.core.handlers;
+
+import java.util.Dictionary;
+
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.FieldInterceptor;
+import org.apache.felix.ipojo.PrimitiveHandler;
+import org.apache.felix.ipojo.annotations.Handler;
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * User: guillaume
+ * Date: 24/07/13
+ * Time: 12:08
+ */
+@Handler(namespace = "com.acme", name = "foo")
+public class FooHandler extends PrimitiveHandler {
+
+ @Override
+ public void configure(final Element metadata, final Dictionary configuration) throws ConfigurationException {
+ Element[] elements = metadata.getElements("foo", "com.acme");
+ for (Element foo : elements) {
+ String value = foo.getAttribute("value");
+ String field = foo.getAttribute("field");
+
+ this.getInstanceManager().register(getPojoMetadata().getField(field, "java.lang.String"),
+ new FixedValueFieldInterceptor(value));
+
+ }
+
+ }
+
+ @Override
+ public Object onGet(final Object pojo, final String fieldName, final Object value) {
+ return value;
+ }
+
+ @Override
+ public void stop() {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void start() {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ private static class FixedValueFieldInterceptor implements FieldInterceptor {
+ private final String m_value;
+
+ public FixedValueFieldInterceptor(final String value) {
+ m_value = value;
+ }
+
+ @Override
+ public void onSet(final Object pojo, final String fieldName, final Object value) {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public Object onGet(final Object pojo, final String fieldName, final Object value) {
+ return m_value;
+ }
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/handlers/IgnoredFoo.java
similarity index 61%
copy from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
copy to ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/handlers/IgnoredFoo.java
index 1748cfc..ccbff86 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
+++ b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/handlers/IgnoredFoo.java
@@ -17,15 +17,24 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.runtime.core.handlers;
-import org.objectweb.asm.AnnotationVisitor;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.felix.ipojo.annotations.HandlerBinding;
+import org.apache.felix.ipojo.annotations.Ignore;
/**
-* User: guillaume
-* Date: 30/05/13
-* Time: 17:23
-*/
-public interface Replay {
- void accept(AnnotationVisitor visitor);
+ * User: guillaume
+ * Date: 24/07/13
+ * Time: 12:10
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.CLASS)
+@Ignore
+public @interface IgnoredFoo {
+ String value();
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/HandlerBindingTestService.java
similarity index 75%
copy from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
copy to ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/HandlerBindingTestService.java
index 1748cfc..120d60b 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
+++ b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/HandlerBindingTestService.java
@@ -17,15 +17,13 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
-
-import org.objectweb.asm.AnnotationVisitor;
+package org.apache.felix.ipojo.runtime.core.services;
/**
-* User: guillaume
-* Date: 30/05/13
-* Time: 17:23
-*/
-public interface Replay {
- void accept(AnnotationVisitor visitor);
+ * User: guillaume
+ * Date: 24/07/13
+ * Time: 12:36
+ */
+public interface HandlerBindingTestService {
+ String get(String name);
}
diff --git a/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestHandlerBindingAndIgnoreAnnotation.java b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestHandlerBindingAndIgnoreAnnotation.java
new file mode 100644
index 0000000..d70ea33
--- /dev/null
+++ b/ipojo/manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestHandlerBindingAndIgnoreAnnotation.java
@@ -0,0 +1,84 @@
+/*
+ * 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.runtime.core;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.HandlerFactory;
+import org.apache.felix.ipojo.runtime.core.services.BazService;
+import org.apache.felix.ipojo.runtime.core.services.HandlerBindingTestService;
+import org.junit.Test;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.OptionUtils;
+import org.ow2.chameleon.testing.helpers.BaseTest;
+
+import junit.framework.Assert;
+
+public class TestHandlerBindingAndIgnoreAnnotation extends BaseTest {
+
+ public static final String FACTORY_NAME = "org.apache.felix.ipojo.runtime.core.components.HandlerBindingTestComponent";
+
+ @Test
+ public void testFooHandlerBinding() {
+
+/*
+ HandlerFactory handlerFactory = ipojoHelper.getHandlerFactory("com.acme:foo");
+ assertNotNull(handlerFactory);
+ assertEquals(Factory.VALID, handlerFactory.getState());
+*/
+
+ // verify component's factory is here
+ // verify BazService has been published
+ // --> verify instance has been created
+
+ Factory factory = ipojoHelper.getFactory(FACTORY_NAME);
+ assertNotNull(factory);
+ assertEquals(Factory.VALID, factory.getState());
+
+
+ List<HandlerBindingTestService> services = osgiHelper.getServiceObjects(HandlerBindingTestService.class);
+ assertEquals(1, services.size());
+
+ HandlerBindingTestService baz = services.get(0);
+ assertEquals("Bonjour", baz.get("greeting"));
+ assertEquals("Welcome", baz.get("welcome"));
+ assertNull(baz.get("ignored"));
+ ipojoHelper.dispose();
+ }
+ @Override
+ protected List<String> getExtraExports() {
+ return Arrays.asList("org.apache.felix.ipojo.runtime.core.components");
+ }
+
+ @Override
+ protected Option[] getCustomOptions() {
+ return new Option[] {CoreOptions.vmOption("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000")};
+ //return new Option[] {CoreOptions.vmOptions("-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000")};
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ClassMetadataCollector.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ClassMetadataCollector.java
index 79a738f..47e65e1 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ClassMetadataCollector.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ClassMetadataCollector.java
@@ -99,15 +99,6 @@
*/
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- /*
- * Visible annotations are mostly destined to be read by reflection
- * at runtime. We retain runtime visible annotations on component
- * as they are and left them out in meta-data calculation.
- */
- if (visible) {
- return null;
- }
-
// Return the visitor to be executed (may be null)
return registry.selection(workbench)
.type(this, node)
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/AnnotationDiscovery.java
similarity index 79%
copy from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
copy to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/AnnotationDiscovery.java
index 1748cfc..9a533b6 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/AnnotationDiscovery.java
@@ -17,15 +17,15 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model;
import org.objectweb.asm.AnnotationVisitor;
/**
-* User: guillaume
-* Date: 30/05/13
-* Time: 17:23
-*/
-public interface Replay {
- void accept(AnnotationVisitor visitor);
+ * User: guillaume
+ * Date: 09/07/13
+ * Time: 14:42
+ */
+public interface AnnotationDiscovery {
+ AnnotationVisitor visitAnnotation(String desc);
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/AnnotationType.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/AnnotationType.java
new file mode 100644
index 0000000..4fcbd73
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/AnnotationType.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.manipulator.metadata.annotation.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.objectweb.asm.Type;
+
+/**
+ * User: guillaume
+ * Date: 27/06/13
+ * Time: 13:37
+ */
+public class AnnotationType {
+ private final Type type;
+ private final List<Playback> m_playbacks = new ArrayList<Playback>();
+
+ public AnnotationType(final Type type) {
+ this.type = type;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public List<Playback> getPlaybacks() {
+ return m_playbacks;
+ }
+
+ public void traverse(AnnotationDiscovery visitor) {
+ for (Playback playback : m_playbacks) {
+ playback.accept(visitor);
+ }
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/Playback.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/Playback.java
new file mode 100644
index 0000000..12802f0
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/Playback.java
@@ -0,0 +1,42 @@
+/*
+ * 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.manipulator.metadata.annotation.model;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationDiscovery;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+
+/**
+ * User: guillaume
+ * Date: 08/07/13
+ * Time: 16:30
+ */
+public interface Playback {
+ void accept(FieldVisitor visitor);
+
+ void accept(ClassVisitor visitor);
+
+ void accept(MethodVisitor visitor);
+
+ void accept(MethodVisitor visitor, int index);
+
+ void accept(AnnotationDiscovery visitor);
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/ChainedAnnotationDiscovery.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/ChainedAnnotationDiscovery.java
new file mode 100644
index 0000000..caea0b1
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/ChainedAnnotationDiscovery.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.discovery;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationDiscovery;
+import org.apache.felix.ipojo.manipulator.util.ChainedAnnotationVisitor;
+import org.objectweb.asm.AnnotationVisitor;
+
+/**
+ * User: guillaume
+ * Date: 10/07/13
+ * Time: 10:48
+ */
+public class ChainedAnnotationDiscovery implements AnnotationDiscovery {
+
+ private List<AnnotationDiscovery> m_discoveries = new ArrayList<AnnotationDiscovery>();
+
+ public List<AnnotationDiscovery> getDiscoveries() {
+ return m_discoveries;
+ }
+
+ public AnnotationVisitor visitAnnotation(final String desc) {
+ ChainedAnnotationVisitor chain = null;
+ for (AnnotationDiscovery discovery : m_discoveries) {
+ AnnotationVisitor visitor = discovery.visitAnnotation(desc);
+ if (visitor != null) {
+ if (chain == null) {
+ chain = new ChainedAnnotationVisitor();
+ }
+ chain.getVisitors().add(visitor);
+ }
+ }
+ return chain;
+ }
+
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/HandlerBindingDiscovery.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/HandlerBindingDiscovery.java
new file mode 100644
index 0000000..224f423
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/HandlerBindingDiscovery.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.discovery;
+
+import org.apache.felix.ipojo.annotations.HandlerBinding;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationDiscovery;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * User: guillaume
+ * Date: 09/07/13
+ * Time: 14:52
+ */
+public class HandlerBindingDiscovery extends EmptyVisitor implements AnnotationDiscovery {
+
+ public static final String HANDLER_BINDING_DESCRIPTOR = Type.getType(HandlerBinding.class).getDescriptor();
+
+ private boolean m_handlerBinding = false;
+ private String m_value = null;
+ private String m_namespace = null;
+
+ public AnnotationVisitor visitAnnotation(final String desc) {
+ if (HANDLER_BINDING_DESCRIPTOR.equals(desc)) {
+ m_handlerBinding = true;
+ return this;
+ }
+ return null;
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ if ("value".equals(name)) {
+ m_value = (String) value;
+ }
+ if ("namespace".equals(name)) {
+ m_namespace = (String) value;
+ }
+ }
+
+ public boolean isHandlerBinding() {
+ return m_handlerBinding;
+ }
+
+ public String getValue() {
+ return m_value;
+ }
+
+ public String getNamespace() {
+ return m_namespace;
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/IgnoredDiscovery.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/IgnoredDiscovery.java
new file mode 100644
index 0000000..71c7cc0
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/IgnoredDiscovery.java
@@ -0,0 +1,48 @@
+/*
+ * 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.manipulator.metadata.annotation.model.discovery;
+
+import org.apache.felix.ipojo.annotations.Ignore;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationDiscovery;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+
+/**
+ * User: guillaume
+ * Date: 09/07/13
+ * Time: 14:52
+ */
+public class IgnoredDiscovery implements AnnotationDiscovery {
+
+ public static final String IGNORE_DESCRIPTOR = Type.getType(Ignore.class).getDescriptor();
+
+ private boolean m_ignore = false;
+
+ public AnnotationVisitor visitAnnotation(final String desc) {
+ if (IGNORE_DESCRIPTOR.equals(desc)) {
+ m_ignore = true;
+ }
+ return null;
+ }
+
+ public boolean isIgnore() {
+ return m_ignore;
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/StereotypeDiscovery.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/StereotypeDiscovery.java
new file mode 100644
index 0000000..a8438da
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/discovery/StereotypeDiscovery.java
@@ -0,0 +1,48 @@
+/*
+ * 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.manipulator.metadata.annotation.model.discovery;
+
+import org.apache.felix.ipojo.annotations.Stereotype;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationDiscovery;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+
+/**
+ * User: guillaume
+ * Date: 09/07/13
+ * Time: 14:52
+ */
+public class StereotypeDiscovery implements AnnotationDiscovery {
+
+ public static final String STEREOTYPE_DESCRIPTOR = Type.getType(Stereotype.class).getDescriptor();
+
+ private boolean m_stereotype = false;
+
+ public AnnotationVisitor visitAnnotation(final String desc) {
+ if (STEREOTYPE_DESCRIPTOR.equals(desc)) {
+ m_stereotype = true;
+ }
+ return null;
+ }
+
+ public boolean isStereotype() {
+ return m_stereotype;
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteral.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteral.java
new file mode 100644
index 0000000..6da7dac
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteral.java
@@ -0,0 +1,77 @@
+/*
+ * 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.manipulator.metadata.annotation.model.literal;
+
+import static java.lang.String.format;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * User: guillaume
+ * Date: 28/06/13
+ * Time: 11:39
+ */
+public abstract class AnnotationLiteral<T extends Annotation> implements Annotation {
+
+ private Class<? extends Annotation> annotationType;
+
+ public Class<? extends Annotation> annotationType() {
+ if (annotationType == null) {
+ annotationType = findAnnotationType(getClass());
+ if (annotationType == null) {
+ throw new IllegalStateException(
+ format("Annotation %s does not specify its annotation type (T) in AnnotationLiteral<T>",
+ getClass().getName())
+ );
+ }
+ }
+ return annotationType;
+ }
+
+ public org.objectweb.asm.Type getType() {
+ return org.objectweb.asm.Type.getType(annotationType());
+ }
+
+ private static Class<Annotation> findAnnotationType(final Class<? extends AnnotationLiteral> type) {
+ Class<?> implementer = findImplementer(type);
+ return findTypeParameter(implementer);
+ }
+
+ private static Class<Annotation> findTypeParameter(final Class<?> clazz) {
+ // Get the T of AnnotationLiteral<T>
+ Type type = clazz.getGenericSuperclass();
+ if (type instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType) type;
+ return (Class<Annotation>) pType.getActualTypeArguments()[0];
+ }
+ return null;
+ }
+
+ private static Class<? extends AnnotationLiteral> findImplementer(final Class<? extends AnnotationLiteral> type) {
+ Class<? extends AnnotationLiteral> superClass = type.getSuperclass().asSubclass(AnnotationLiteral.class);
+ if (AnnotationLiteral.class.equals(superClass)) {
+ return type;
+ } else {
+ return findImplementer(superClass);
+ }
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationPlayback.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationPlayback.java
new file mode 100644
index 0000000..3b7a529
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationPlayback.java
@@ -0,0 +1,264 @@
+/*
+ * 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.manipulator.metadata.annotation.model.literal;
+
+import static java.lang.String.format;
+import static org.objectweb.asm.Type.getType;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationDiscovery;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.Playback;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+
+/**
+ * User: guillaume
+ * Date: 08/07/13
+ * Time: 17:15
+ */
+public class AnnotationPlayback implements Playback {
+
+ public static final List<? extends Class<? extends Serializable>> BOXED_TYPES = Arrays.asList(Byte.class, Long.class, Character.class, Boolean.class, Double.class, Float.class, Integer.class, Short.class);
+ private final Annotation m_annotation;
+ private final Type m_annotationType;
+
+ public AnnotationPlayback(final Annotation annotation) {
+ m_annotation = annotation;
+ m_annotationType = Type.getType(annotation.annotationType());
+ }
+
+ private Map<String, Object> getValues() {
+ Map<String, Object> values = new HashMap<String, Object>();
+ for (Method method : m_annotation.annotationType().getDeclaredMethods()) {
+ try {
+ values.put(method.getName(), method.invoke(m_annotation));
+ } catch (Throwable t) {
+ throw new IllegalStateException(
+ format("Cannot get value of the %s.%s attribute",
+ m_annotation.annotationType().getSimpleName(),
+ method.getName()),
+ t
+ );
+ }
+ }
+ return values;
+ }
+ public void accept(final FieldVisitor visitor) {
+ AnnotationVisitor av = visitor.visitAnnotation(m_annotationType.getDescriptor(),
+ true);
+ if (av != null) {
+ accept(av);
+ }
+ }
+
+ public void accept(final ClassVisitor visitor) {
+ AnnotationVisitor av = visitor.visitAnnotation(m_annotationType.getDescriptor(),
+ true);
+ if (av != null) {
+ accept(av);
+ }
+ }
+
+ public void accept(final MethodVisitor visitor) {
+ AnnotationVisitor av = visitor.visitAnnotation(m_annotationType.getDescriptor(),
+ true);
+ if (av != null) {
+ accept(av);
+ }
+ }
+
+ public void accept(final MethodVisitor visitor, final int index) {
+ AnnotationVisitor av = visitor.visitParameterAnnotation(index,
+ m_annotationType.getDescriptor(),
+ true);
+ if (av != null) {
+ accept(av);
+ }
+ }
+
+ public void accept(final AnnotationDiscovery visitor) {
+ AnnotationVisitor av = visitor.visitAnnotation(m_annotationType.getDescriptor());
+ if (av != null) {
+ accept(av);
+ }
+ }
+
+ private void accept(final AnnotationVisitor visitor) {
+ // As per the ASM doc, visit methods must be called in a given order:
+ // 1. visit()
+ // 2. visitEnum()
+ // 3. visitAnnotation()
+ // 4. visitArray()
+
+ // So values must be sorted
+ Map<String, Object> values = getValues();
+ accept(values, visitor);
+ acceptEnum(values, visitor);
+ acceptAnnotation(values, visitor);
+ acceptArray(values, visitor);
+
+ // Do not forget to visitEnd()
+ visitor.visitEnd();
+
+ // TODO This should disappear, only useful for testing
+ if (!values.isEmpty()) {
+ // We missed something during serialization
+ throw new IllegalStateException(
+ format("Attributes of @%s could not be serialized: %s",
+ m_annotation.annotationType().getSimpleName(),
+ values.keySet())
+ );
+ }
+ }
+
+ private void acceptAnnotation(final Map<String, Object> values, final AnnotationVisitor visitor) {
+ Map<String, Object> copy = new HashMap<String, Object>(values);
+ for (Map.Entry<String, Object> entry : copy.entrySet()) {
+
+ Class<?> type = entry.getValue().getClass();
+ if (Annotation.class.isAssignableFrom(type)) {
+
+ Annotation annotation = (Annotation) entry.getValue();
+ AnnotationVisitor annotationVisitor = visitor.visitAnnotation(entry.getKey(),
+ getType(annotation.annotationType()).getDescriptor());
+ if (annotationVisitor != null) {
+ AnnotationPlayback playback = new AnnotationPlayback(annotation);
+ playback.accept(annotationVisitor);
+ }
+
+ values.remove(entry.getKey());
+ }
+ }
+ }
+
+ private void acceptEnum(final Map<String, Object> values, final AnnotationVisitor visitor) {
+
+ Map<String, Object> copy = new HashMap<String, Object>(values);
+ for (Map.Entry<String, Object> entry : copy.entrySet()) {
+
+ Class<?> type = entry.getValue().getClass();
+ if (type.isEnum()) {
+ Enum<?> enumValue = (Enum<?>) entry.getValue();
+ visitor.visitEnum(entry.getKey(),
+ getType(type).getDescriptor(),
+ enumValue.name());
+
+ values.remove(entry.getKey());
+ }
+ }
+ }
+
+ private void accept(final Map<String, Object> values, final AnnotationVisitor visitor) {
+
+ Map<String, Object> copy = new HashMap<String, Object>(values);
+ for (Map.Entry<String, Object> entry : copy.entrySet()) {
+
+ Class<?> type = entry.getValue().getClass();
+ if (isSimpleType(type)) {
+
+ // Accept Byte, Boolean, Character, Short, Integer, Long, Float, Double
+ // Accept String
+ // Accept Array of byte, boolean, char, short, int, long, float, double
+ visitor.visit(entry.getKey(), transform(entry.getValue()));
+
+ values.remove(entry.getKey());
+ }
+ }
+ }
+
+ private boolean isSimpleType(final Class<?> type) {
+ return isPrimitive(type) ||
+ String.class.equals(type) ||
+ Class.class.equals(type) ||
+ (type.isArray() && isPrimitive(type.getComponentType()));
+ }
+
+ private boolean isPrimitive(final Class<?> type) {
+ if (type.isPrimitive()) {
+ return true;
+ }
+
+ if (BOXED_TYPES.contains(type)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private void acceptArray(final Map<String, Object> values, final AnnotationVisitor visitor) {
+ Map<String, Object> copy = new HashMap<String, Object>(values);
+ for (Map.Entry<String, Object> entry : copy.entrySet()) {
+
+ Class<?> type = entry.getValue().getClass();
+ if (type.isArray()) {
+
+ // Simple arrays have been visited using AnnotationVisitor.visit(String, Object)
+
+ AnnotationVisitor arrayVisitor = visitor.visitArray(entry.getKey());
+ if (arrayVisitor != null) {
+ Object[] array = (Object[]) entry.getValue();
+ Class<?> componentType = array.getClass().getComponentType();
+ Type asmType = Type.getType(componentType);
+
+ if (componentType.isEnum()) {
+ for (Object o : array) {
+ Enum eValue = (Enum) o;
+ arrayVisitor.visitEnum(null, asmType.getDescriptor(), eValue.name());
+ }
+ } else if (componentType.isAnnotation()) {
+ for (Object o : array) {
+ Annotation annotation = (Annotation) o;
+ AnnotationVisitor annotationVisitor = arrayVisitor.visitAnnotation(null, asmType.getDescriptor());
+ if (annotationVisitor != null) {
+ AnnotationPlayback playback = new AnnotationPlayback(annotation);
+ playback.accept(annotationVisitor);
+ }
+ }
+ } else {
+ for (Object o : array) {
+ arrayVisitor.visit(null, transform(o));
+ }
+ }
+
+ arrayVisitor.visitEnd();
+ }
+
+ values.remove(entry.getKey());
+ }
+ }
+ }
+
+ private Object transform(final Object value) {
+ if (value instanceof Class) {
+ return getType((Class) value);
+ }
+ return value;
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/AnnotationParser.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/AnnotationParser.java
new file mode 100644
index 0000000..fdb000d
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/AnnotationParser.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.manipulator.metadata.annotation.model.parser;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
+import org.objectweb.asm.ClassReader;
+
+/**
+ * User: guillaume
+ * Date: 01/07/13
+ * Time: 15:49
+ */
+public class AnnotationParser {
+ public AnnotationType read(byte[] resource) {
+ ClassReader reader = new ClassReader(resource);
+ AnnotationTypeVisitor visitor = new AnnotationTypeVisitor();
+ reader.accept(visitor, ClassReader.SKIP_CODE);
+ return visitor.getAnnotationType();
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/AnnotationTypeVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/AnnotationTypeVisitor.java
new file mode 100644
index 0000000..77e9c53
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/AnnotationTypeVisitor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.manipulator.metadata.annotation.model.parser;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay.AnnotationVisitorPlayback;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * User: guillaume
+ * Date: 01/07/13
+ * Time: 15:59
+ */
+public class AnnotationTypeVisitor extends EmptyVisitor implements ClassVisitor {
+
+ private AnnotationType annotationType;
+
+ @Override
+ public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {
+ annotationType = new AnnotationType(Type.getObjectType(name));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
+ // Build annotations of this annotation type
+ AnnotationVisitorPlayback playback = new AnnotationVisitorPlayback(desc, visible);
+ annotationType.getPlaybacks().add(playback);
+ return playback;
+ }
+
+ public AnnotationType getAnnotationType() {
+ return annotationType;
+ }
+
+ // Note: if we override visitMethod here, we could get the annotation's default values.
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/AnnotationRecorder.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/AnnotationRecorder.java
similarity index 78%
rename from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/AnnotationRecorder.java
rename to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/AnnotationRecorder.java
index b0afaa4..47d1071 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/AnnotationRecorder.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/AnnotationRecorder.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay;
import java.util.ArrayList;
import java.util.List;
@@ -31,34 +31,34 @@
*/
public class AnnotationRecorder implements AnnotationVisitor, Replay {
- private List<Replay> record = new ArrayList<Replay>();
+ private List<Replay> m_replays = new ArrayList<Replay>();
public void visit(final String name, final Object value) {
- record.add(new Visit(name, value));
+ m_replays.add(new Visit(name, value));
}
public void visitEnum(final String name, final String desc, final String value) {
- record.add(new VisitEnum(name, desc, value));
+ m_replays.add(new VisitEnum(name, desc, value));
}
public AnnotationVisitor visitAnnotation(final String name, final String desc) {
AnnotationRecorder sub = new AnnotationRecorder();
- record.add(new VisitAnnotation(name, desc, sub));
+ m_replays.add(new VisitAnnotation(name, desc, sub));
return sub;
}
public AnnotationVisitor visitArray(final String name) {
AnnotationRecorder sub = new AnnotationRecorder();
- record.add(new VisitArray(name, sub));
+ m_replays.add(new VisitArray(name, sub));
return sub;
}
public void visitEnd() {
- record.add(new VisitEnd());
+ m_replays.add(new VisitEnd());
}
public void accept(final AnnotationVisitor visitor) {
- for (Replay replay : record) {
+ for (Replay replay : m_replays) {
replay.accept(visitor);
}
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/RootAnnotationRecorder.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/AnnotationVisitorPlayback.java
similarity index 74%
rename from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/RootAnnotationRecorder.java
rename to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/AnnotationVisitorPlayback.java
index 70548bd..95dd6eb 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/RootAnnotationRecorder.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/AnnotationVisitorPlayback.java
@@ -17,8 +17,10 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationDiscovery;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.Playback;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
@@ -26,14 +28,14 @@
/**
* User: guillaume
- * Date: 30/05/13
- * Time: 19:20
+ * Date: 08/07/13
+ * Time: 16:07
*/
-public class RootAnnotationRecorder extends AnnotationRecorder {
+public class AnnotationVisitorPlayback extends AnnotationRecorder implements Playback {
private final String m_desc;
private final boolean m_visible;
- public RootAnnotationRecorder(final String desc, final boolean visible) {
+ public AnnotationVisitorPlayback(final String desc, final boolean visible) {
m_desc = desc;
m_visible = visible;
}
@@ -65,4 +67,11 @@
accept(av);
}
}
+
+ public void accept(final AnnotationDiscovery visitor) {
+ AnnotationVisitor av = visitor.visitAnnotation(m_desc);
+ if (av != null) {
+ accept(av);
+ }
+ }
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/Replay.java
similarity index 91%
rename from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
rename to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/Replay.java
index 1748cfc..1597936 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/Replay.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay;
import org.objectweb.asm.AnnotationVisitor;
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Visit.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/Visit.java
similarity index 93%
rename from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Visit.java
rename to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/Visit.java
index e0d46c2..4c3eff2 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Visit.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/Visit.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay;
import org.objectweb.asm.AnnotationVisitor;
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitAnnotation.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitAnnotation.java
similarity index 94%
rename from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitAnnotation.java
rename to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitAnnotation.java
index ee61d7d..59a30e5 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitAnnotation.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitAnnotation.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay;
import org.objectweb.asm.AnnotationVisitor;
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitArray.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitArray.java
similarity index 93%
rename from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitArray.java
rename to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitArray.java
index 124d75a..5a4149e 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitArray.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitArray.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay;
import org.objectweb.asm.AnnotationVisitor;
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitEnd.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitEnd.java
similarity index 92%
rename from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitEnd.java
rename to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitEnd.java
index 51ddb58..2bdebd5 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitEnd.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitEnd.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay;
import org.objectweb.asm.AnnotationVisitor;
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitEnum.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitEnum.java
similarity index 93%
rename from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitEnum.java
rename to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitEnum.java
index 12708d6..ce044d2 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/VisitEnum.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/VisitEnum.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay;
import org.objectweb.asm.AnnotationVisitor;
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/AnnotationRegistry.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/AnnotationRegistry.java
deleted file mode 100644
index 5de31f5..0000000
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/AnnotationRegistry.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.manipulator.metadata.annotation.registry;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay.RootAnnotationRecorder;
-import org.objectweb.asm.Type;
-
-/**
- * User: guillaume
- * Date: 30/05/13
- * Time: 20:35
- */
-public class AnnotationRegistry {
-
- /**
- * Contains the annotations definitions for the given Stereotype annotation.
- */
- private Map<Type, List<RootAnnotationRecorder>> stereotypes = new HashMap<Type, List<RootAnnotationRecorder>>();
-
- /**
- * Other annotations.
- */
- private List<Type> unbound = new ArrayList<Type>();
-
- public void addStereotype(Type type, List<RootAnnotationRecorder> recorders) {
- stereotypes.put(type, recorders);
- }
-
- public void addUnbound(Type type) {
- unbound.add(type);
- }
-
- public List<RootAnnotationRecorder> getRecorders(Type type) {
- List<RootAnnotationRecorder> recorders = stereotypes.get(type);
- if (recorders == null) {
- return Collections.emptyList();
- }
- return recorders;
- }
-
- public boolean isStereotype(Type type) {
- return stereotypes.get(type) != null;
- }
-
- public boolean isUnbound(Type type) {
- return unbound.contains(type);
- }
-
- public boolean isUnknown(Type type) {
- return !isStereotype(type) && !isUnbound(type);
- }
-}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Binding.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Binding.java
index e60e751..fc6a963 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Binding.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Binding.java
@@ -19,8 +19,11 @@
package org.apache.felix.ipojo.manipulator.metadata.annotation.registry;
+import static java.lang.String.format;
+
import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
import org.apache.felix.ipojo.manipulator.spi.Predicate;
+import org.objectweb.asm.Type;
import java.lang.annotation.Annotation;
@@ -29,15 +32,15 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class Binding {
- private Class<? extends Annotation> annotationType;
+ private Type annotationType;
private AnnotationVisitorFactory factory;
private Predicate predicate;
- public Class<? extends Annotation> getAnnotationType() {
+ public Type getAnnotationType() {
return annotationType;
}
- public void setAnnotationType(Class<? extends Annotation> annotationType) {
+ public void setAnnotationType(Type annotationType) {
this.annotationType = annotationType;
}
@@ -56,4 +59,9 @@
public void setPredicate(Predicate predicate) {
this.predicate = predicate;
}
+
+ @Override
+ public String toString() {
+ return format("Binding[@%s->%s]", annotationType.getClassName(), factory);
+ }
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistry.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistry.java
index cefbf20..0c80ce7 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistry.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistry.java
@@ -19,65 +19,25 @@
package org.apache.felix.ipojo.manipulator.metadata.annotation.registry;
-import org.apache.felix.ipojo.manipulator.Reporter;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
-import org.apache.felix.ipojo.manipulator.spi.Predicate;
-import org.objectweb.asm.Type;
-
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
/**
- * Stores all the {@link Binding}s coming from the {@link org.apache.felix.ipojo.manipulator.spi.Module}.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ * User: guillaume
+ * Date: 11/07/13
+ * Time: 16:12
*/
-public class BindingRegistry {
- private Map<String, List<Binding>> tree;
- private Reporter reporter;
+public interface BindingRegistry {
+ void addBindings(Iterable<Binding> bindings);
+
+ Selection selection(ComponentWorkbench workbench);
/**
- * When no other Binding is selected, the default Bindings list is used.
+ * Find the list of {@link Binding} registered with the given annotation type.
+ * This method returns an empty List if no bindings are registered.
+ * @param descriptor denotes the annotation's type
+ * @return the list of {@link Binding} registered with the given descriptor, the list may be empty if no bindings are found.
*/
- private List<Binding> defaultBindings;
-
- public BindingRegistry(Reporter reporter) {
- this.reporter = reporter;
- tree = new HashMap<String, List<Binding>>();
- defaultBindings = new ArrayList<Binding>();
- }
-
- /**
- * Stores the given Bindings
- */
- public void addBindings(Iterable<Binding> bindings) {
- for (Binding binding : bindings) {
- Type type = Type.getType(binding.getAnnotationType());
-
- List<Binding> potential = tree.get(type.getDescriptor());
- if (potential == null) {
- // Annotation is not already found in supported list
- potential = new ArrayList<Binding>();
- tree.put(type.getDescriptor(), potential);
- }
-
- potential.add(binding);
- }
- }
-
- /**
- * Initiate a {@link Selection} for the given workbench.
- */
- public Selection selection(ComponentWorkbench workbench) {
- return new Selection(this, workbench, reporter);
- }
-
- public List<Binding> getBindings(String descriptor) {
- return tree.get(descriptor);
- }
-
- public List<Binding> getDefaultBindings() {
- return defaultBindings;
- }
+ List<Binding> getBindings(String descriptor);
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/CompletableBindingRegistry.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/CompletableBindingRegistry.java
new file mode 100644
index 0000000..398db41
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/CompletableBindingRegistry.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.manipulator.metadata.annotation.registry;
+
+import java.util.List;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.objectweb.asm.Type;
+
+/**
+ * User: guillaume
+ * Date: 11/07/13
+ * Time: 16:09
+ */
+public abstract class CompletableBindingRegistry implements BindingRegistry {
+ private final BindingRegistry m_delegate;
+ private final Reporter m_reporter;
+
+ public CompletableBindingRegistry(final BindingRegistry delegate, final Reporter reporter) {
+ m_delegate = delegate;
+ m_reporter = reporter;
+ }
+
+ public List<Binding> getBindings(final String descriptor) {
+ List<Binding> bindings = m_delegate.getBindings(descriptor);
+ if (bindings.isEmpty()) {
+ List<Binding> ignored = createBindings(Type.getType(descriptor));
+ m_delegate.addBindings(ignored);
+ return ignored;
+ }
+ return bindings;
+ }
+
+ protected abstract List<Binding> createBindings(final Type type);
+
+ public void addBindings(final Iterable<Binding> bindings) {
+ m_delegate.addBindings(bindings);
+ }
+
+ public Selection selection(final ComponentWorkbench workbench) {
+ return new Selection(this, workbench, m_reporter);
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/DefaultBindingRegistry.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/DefaultBindingRegistry.java
new file mode 100644
index 0000000..c41e577
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/DefaultBindingRegistry.java
@@ -0,0 +1,79 @@
+/*
+ * 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.manipulator.metadata.annotation.registry;
+
+import static java.util.Collections.emptyList;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.objectweb.asm.Type;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Stores all the {@link Binding}s coming from the {@link org.apache.felix.ipojo.manipulator.spi.Module}.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DefaultBindingRegistry implements BindingRegistry {
+ private final Map<String, List<Binding>> tree = new HashMap<String, List<Binding>>();
+ protected final Reporter reporter;
+
+ public DefaultBindingRegistry(Reporter reporter) {
+ this.reporter = reporter;
+ }
+
+ /**
+ * Stores the given Bindings
+ */
+ public void addBindings(Iterable<Binding> bindings) {
+ for (Binding binding : bindings) {
+ Type type = binding.getAnnotationType();
+
+ List<Binding> potential = tree.get(type.getDescriptor());
+ if (potential == null) {
+ // Annotation is not already found in supported list
+ potential = new ArrayList<Binding>();
+ tree.put(type.getDescriptor(), potential);
+ }
+
+ reporter.trace("Registered @%s", type.getClassName());
+ potential.add(binding);
+ }
+ }
+
+ /**
+ * Initiate a {@link Selection} for the given workbench.
+ */
+ public Selection selection(ComponentWorkbench workbench) {
+ return new Selection(this, workbench, reporter);
+ }
+
+ public List<Binding> getBindings(String descriptor) {
+ List<Binding> bindings = tree.get(descriptor);
+ if (bindings == null) {
+ bindings = emptyList();
+ }
+ return bindings;
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/IgnoreAllBindingRegistry.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/IgnoreAllBindingRegistry.java
new file mode 100644
index 0000000..ca84dcb
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/IgnoreAllBindingRegistry.java
@@ -0,0 +1,46 @@
+/*
+ * 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.manipulator.metadata.annotation.registry;
+
+import static java.util.Collections.singletonList;
+
+import java.util.List;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ignore.NullBinding;
+import org.objectweb.asm.Type;
+
+/**
+ * User: guillaume
+ * Date: 11/07/13
+ * Time: 16:09
+ */
+public class IgnoreAllBindingRegistry extends CompletableBindingRegistry {
+
+ public IgnoreAllBindingRegistry(final BindingRegistry delegate, final Reporter reporter) {
+ super(delegate, reporter);
+ }
+
+ @Override
+ protected List<Binding> createBindings(final Type type) {
+ return singletonList((Binding) new NullBinding(type));
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/LegacyGenericBindingRegistry.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/LegacyGenericBindingRegistry.java
new file mode 100644
index 0000000..2f9c711
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/LegacyGenericBindingRegistry.java
@@ -0,0 +1,98 @@
+/*
+ * 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.manipulator.metadata.annotation.registry;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.alwaysTrue;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.FieldGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.MethodGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.ParameterGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.TypeGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Elements;
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * User: guillaume
+ * Date: 11/07/13
+ * Time: 16:09
+ */
+public class LegacyGenericBindingRegistry extends CompletableBindingRegistry {
+ public static final Pattern CUSTOM_HANDLER_PATTERN = Pattern.compile("(.*\\.ipojo\\..*)|(.*\\.handler\\..*)");
+
+ public LegacyGenericBindingRegistry(final BindingRegistry delegate, final Reporter reporter) {
+ super(delegate, reporter);
+ }
+
+ @Override
+ protected List<Binding> createBindings(final Type type) {
+ if (CUSTOM_HANDLER_PATTERN.matcher(type.getClassName()).matches()) {
+ Binding binding = new Binding();
+ binding.setAnnotationType(type);
+ binding.setPredicate(alwaysTrue());
+ binding.setFactory(new AnnotationVisitorFactory() {
+ // Need to build a new Element instance for each created visitor
+ public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+ if (context.getNode() instanceof ClassNode) {
+ return new TypeGenericVisitor(context.getWorkbench(),
+ Elements.buildElement(type));
+ } else if (context.getNode() instanceof FieldNode) {
+ return new FieldGenericVisitor(context.getWorkbench(),
+ Elements.buildElement(type),
+ (FieldNode) context.getNode());
+
+ } else if ((context.getNode() instanceof MethodNode) &&
+ (context.getParameterIndex() == BindingContext.NO_INDEX)) {
+ return new MethodGenericVisitor(context.getWorkbench(),
+ Elements.buildElement(type),
+ (MethodNode) context.getNode());
+ } else {
+ // last case: method parameter annotation
+ return new ParameterGenericVisitor(context.getWorkbench(),
+ Elements.buildElement(type),
+ (MethodNode) context.getNode(),
+ context.getParameterIndex());
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "LegacyGenericVisitorFactory";
+ }
+ });
+
+ // Return the produced generic binding
+ return singletonList(binding);
+ }
+
+ return emptyList();
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/MetaAnnotationBindingRegistry.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/MetaAnnotationBindingRegistry.java
new file mode 100644
index 0000000..8ea953f
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/MetaAnnotationBindingRegistry.java
@@ -0,0 +1,160 @@
+/*
+ * 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.manipulator.metadata.annotation.registry;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.unmodifiableList;
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.alwaysTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.ipojo.annotations.HandlerBinding;
+import org.apache.felix.ipojo.annotations.Ignore;
+import org.apache.felix.ipojo.annotations.Stereotype;
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.ResourceStore;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.discovery.ChainedAnnotationDiscovery;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.discovery.HandlerBindingDiscovery;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.discovery.IgnoredDiscovery;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.discovery.StereotypeDiscovery;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.AnnotationParser;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.GenericVisitorFactory;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ignore.NullBinding;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype.StereotypeVisitorFactory;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Elements;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.Type;
+
+/**
+ * The {@link MetaAnnotationBindingRegistry} is a registry that tries to complete its list
+ * of bindings when an unknown one is detected.
+ * It uses the given {@link ResourceStore} to parse the annotation's type and find if
+ * it's annotated with @{@link org.apache.felix.ipojo.annotations.Stereotype},
+ * @{@link org.apache.felix.ipojo.annotations.HandlerBinding} or @{@link org.apache.felix.ipojo.annotations.Ignore}
+ */
+public class MetaAnnotationBindingRegistry extends CompletableBindingRegistry {
+
+ private ResourceStore m_store;
+ private Reporter m_reporter;
+
+ public MetaAnnotationBindingRegistry(final BindingRegistry delegate, final Reporter reporter, final ResourceStore store) {
+ super(delegate, reporter);
+ this.m_reporter = reporter;
+ this.m_store = store;
+ addBindings(nullBindingsForMetaAnnotations());
+ }
+
+ protected Iterable<Binding> nullBindingsForMetaAnnotations() {
+ // Do not re-apply meta-annotations
+ ArrayList<Binding> bindings = new ArrayList<Binding>();
+ bindings.add(new NullBinding(Type.getType(Stereotype.class)));
+ bindings.add(new NullBinding(Type.getType(HandlerBinding.class)));
+ bindings.add(new NullBinding(Type.getType(Ignore.class)));
+ return bindings;
+ }
+
+ @Override
+ protected List<Binding> createBindings(final Type type) {
+
+ // Parse the annotation
+ byte[] bytes;
+ try {
+ bytes = m_store.read(type.getInternalName().concat(".class"));
+ } catch (IOException e) {
+ // Annotation type cannot be read
+ m_reporter.trace("Could not read bytecode for @%s", type.getClassName());
+ return emptyList();
+ }
+ AnnotationParser parser = new AnnotationParser();
+ AnnotationType annotationType = parser.read(bytes);
+
+ // Search meta-annotations
+ ChainedAnnotationDiscovery chain = new ChainedAnnotationDiscovery();
+ StereotypeDiscovery stereotypeDiscovery = new StereotypeDiscovery();
+ HandlerBindingDiscovery handlerBindingDiscovery = new HandlerBindingDiscovery();
+ IgnoredDiscovery ignoredDiscovery = new IgnoredDiscovery();
+ chain.getDiscoveries().add(stereotypeDiscovery);
+ chain.getDiscoveries().add(handlerBindingDiscovery);
+ chain.getDiscoveries().add(ignoredDiscovery);
+
+ annotationType.traverse(chain);
+
+ // Produced Bindings
+ List<Binding> bindings = new ArrayList<Binding>();
+
+ // @Stereotype support
+ if (stereotypeDiscovery.isStereotype()) {
+ m_reporter.trace("@Stereotype detected: @%s", type.getClassName());
+ Binding binding = new Binding();
+ binding.setAnnotationType(type);
+ binding.setPredicate(alwaysTrue());
+ binding.setFactory(new StereotypeVisitorFactory(annotationType));
+
+ bindings.add(binding);
+ }
+
+ // @HandlerBinding support
+ if (handlerBindingDiscovery.isHandlerBinding()) {
+
+ m_reporter.trace("@HandlerBinding detected: @%s", type.getClassName());
+ Binding binding = new Binding();
+ binding.setAnnotationType(type);
+ binding.setPredicate(alwaysTrue());
+ final Element element = buildElement(handlerBindingDiscovery, type);
+ binding.setFactory(new GenericVisitorFactory(element.getName(), element.getNameSpace()));
+
+ bindings.add(binding);
+ }
+
+ // Its IMPORTANT that the @Ignore is processed last since it removes existing bindings
+ if (ignoredDiscovery.isIgnore()) {
+ m_reporter.trace("@Ignore detected: @%s", type.getClassName());
+ Binding binding = new NullBinding(type);
+
+ bindings.clear();
+ bindings.add(binding);
+ bindings = unmodifiableList(bindings); // just in case of ...
+ }
+
+ return bindings;
+
+ }
+
+ private Element buildElement(final HandlerBindingDiscovery handler, final Type type) {
+ Element element;
+ if ((handler.getNamespace() == null) &&
+ (handler.getValue() == null)) {
+ // No attributes specified, use annotation type as element's source
+ element = Elements.buildElement(type);
+ } else if ((handler.getNamespace() == null) &&
+ (handler.getValue() != null)) {
+ // Namespace attribute is omitted
+ element = Elements.buildElement(handler.getValue());
+ } else {
+ element = Elements.buildElement(handler.getNamespace(),
+ handler.getValue());
+ }
+ return element;
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Selection.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Selection.java
index 5fb435e..f4fefc2 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Selection.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Selection.java
@@ -22,6 +22,7 @@
import org.apache.felix.ipojo.manipulator.Reporter;
import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.apache.felix.ipojo.manipulator.util.ChainedAnnotationVisitor;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
@@ -34,7 +35,6 @@
import java.lang.annotation.ElementType;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
/**
@@ -42,13 +42,13 @@
* It's a query DSL.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class Selection implements Iterable<AnnotationVisitor> {
+public class Selection {
private BindingRegistry registry;
private ComponentWorkbench workbench;
private Reporter reporter;
private MemberNode node;
- private int index = -1;
+ private int index = BindingContext.NO_INDEX;
private String annotation;
private ElementType elementType = null;
private Object visitor;
@@ -94,32 +94,34 @@
}
public AnnotationVisitor get() {
- Iterator<AnnotationVisitor> i = iterator();
- if (iterator().hasNext()) {
- return i.next();
+ List<AnnotationVisitor> visitors = list();
+
+ if (visitors.isEmpty()) {
+ return null;
}
- return null;
+
+ if (visitors.size() == 1) {
+ return visitors.get(0);
+ }
+
+ ChainedAnnotationVisitor chained = new ChainedAnnotationVisitor();
+ chained.getVisitors().addAll(visitors);
+ return chained;
}
- public Iterator<AnnotationVisitor> iterator() {
-
- List<AnnotationVisitor> visitors = new ArrayList<AnnotationVisitor>();
+ private List<AnnotationVisitor> list() {
BindingContext context = new BindingContext(workbench, reporter, Type.getType(annotation), node, elementType, index, visitor);
List<Binding> predicates = registry.getBindings(annotation);
+ List<AnnotationVisitor> visitors = new ArrayList<AnnotationVisitor>();
if (predicates != null && !predicates.isEmpty()) {
collectMatchingVisitors(predicates, context, visitors);
}
-
- if (visitors.isEmpty() && !registry.getDefaultBindings().isEmpty()) {
- collectMatchingVisitors(registry.getDefaultBindings(), context, visitors);
- }
-
-
- return visitors.iterator();
+ return visitors;
}
+
private void collectMatchingVisitors(List<Binding> bindings, BindingContext context, List<AnnotationVisitor> visitors) {
for (Binding binding : bindings) {
if (binding.getPredicate().matches(context)) {
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/StereotypeParser.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/StereotypeParser.java
deleted file mode 100644
index 672edee..0000000
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/StereotypeParser.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.manipulator.metadata.annotation.stereotype;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay.RootAnnotationRecorder;
-import org.objectweb.asm.ClassReader;
-
-/**
- * User: guillaume
- * Date: 30/05/13
- * Time: 12:42
- */
-public class StereotypeParser {
- private boolean stereotype = false;
- private List<RootAnnotationRecorder> replays = new ArrayList<RootAnnotationRecorder>();
-
- public void read(byte[] resource) {
- ClassReader reader = new ClassReader(resource);
- reader.accept(new StereotypeVisitor(this), ClassReader.SKIP_CODE);
- }
-
- public boolean isStereotype() {
- return stereotype;
- }
-
- public void setStereotype(final boolean stereotype) {
- this.stereotype = stereotype;
- }
-
- public List<RootAnnotationRecorder> getRecorders() {
- return replays;
- }
-}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/StereotypeVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/StereotypeVisitor.java
deleted file mode 100644
index 6216831..0000000
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/StereotypeVisitor.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.manipulator.metadata.annotation.stereotype;
-
-import org.apache.felix.ipojo.annotations.Stereotype;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay.RootAnnotationRecorder;
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.commons.EmptyVisitor;
-
-/**
-* User: guillaume
-* Date: 30/05/13
-* Time: 17:09
-*/
-public class StereotypeVisitor extends EmptyVisitor {
-
- public static final Type MARKER_TYPE = Type.getType(Stereotype.class);
-
- private StereotypeParser m_definition;
-
- public StereotypeVisitor(final StereotypeParser definition) {
- m_definition = definition;
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
- Type annotationType = Type.getType(desc);
- if (MARKER_TYPE.equals(annotationType)) {
- m_definition.setStereotype(true);
- return null;
- }
- RootAnnotationRecorder visitor = new RootAnnotationRecorder(desc, visible);
- m_definition.getRecorders().add(visitor);
- return visitor;
- }
-
- @Override
- public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
- return null;
- }
-
- @Override
- public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) {
- return null;
- }
-
-}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/GenericVisitorFactory.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/GenericVisitorFactory.java
new file mode 100644
index 0000000..c08bdc1
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/GenericVisitorFactory.java
@@ -0,0 +1,73 @@
+/*
+ * 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.manipulator.metadata.annotation.visitor.generic;
+
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+* User: guillaume
+* Date: 11/07/13
+* Time: 14:41
+*/
+public class GenericVisitorFactory implements AnnotationVisitorFactory {
+ private final String m_name;
+ private final String m_namespace;
+
+ public GenericVisitorFactory(final String name, final String namespace) {
+ m_name = name;
+ m_namespace = namespace;
+ }
+
+ // Need to build a new Element instance for each created visitor
+ public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+ if (context.getNode() instanceof ClassNode) {
+ return new TypeGenericVisitor(context.getWorkbench(),
+ new Element(m_name, m_namespace));
+ } else if (context.getNode() instanceof FieldNode) {
+ return new FieldGenericVisitor(context.getWorkbench(),
+ new Element(m_name, m_namespace),
+ (FieldNode) context.getNode());
+
+ } else if ((context.getNode() instanceof MethodNode) &&
+ (context.getParameterIndex() == BindingContext.NO_INDEX)) {
+ return new MethodGenericVisitor(context.getWorkbench(),
+ new Element(m_name, m_namespace),
+ (MethodNode) context.getNode());
+ } else {
+ // last case: method parameter annotation
+ return new ParameterGenericVisitor(context.getWorkbench(),
+ new Element(m_name, m_namespace),
+ (MethodNode) context.getNode(),
+ context.getParameterIndex());
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "GenericVisitorFactory";
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ignore/NullBinding.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ignore/NullBinding.java
new file mode 100644
index 0000000..b736d8b
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ignore/NullBinding.java
@@ -0,0 +1,40 @@
+/*
+ * 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.manipulator.metadata.annotation.visitor.ignore;
+
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.alwaysTrue;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
+import org.objectweb.asm.Type;
+
+/**
+ * User: guillaume
+ * Date: 10/07/13
+ * Time: 15:04
+ */
+public class NullBinding extends Binding {
+ public NullBinding(final Type type) {
+ super();
+ setAnnotationType(type);
+ setPredicate(alwaysTrue());
+ setFactory(NullVisitorFactory.INSTANCE);
+
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ignore/NullVisitorFactory.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ignore/NullVisitorFactory.java
new file mode 100644
index 0000000..c056e9e
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ignore/NullVisitorFactory.java
@@ -0,0 +1,42 @@
+/*
+ * 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.manipulator.metadata.annotation.visitor.ignore;
+
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.objectweb.asm.AnnotationVisitor;
+
+/**
+* User: guillaume
+* Date: 10/07/13
+* Time: 15:05
+*/
+public class NullVisitorFactory implements AnnotationVisitorFactory {
+ public static final AnnotationVisitorFactory INSTANCE = new NullVisitorFactory();
+
+ public AnnotationVisitor newAnnotationVisitor(final BindingContext context) {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName();
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/FieldStereotypeVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/FieldStereotypeVisitor.java
index 913677e..3dbf020 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/FieldStereotypeVisitor.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/FieldStereotypeVisitor.java
@@ -19,10 +19,8 @@
package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype;
-import java.util.List;
-
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay.RootAnnotationRecorder;
-import org.objectweb.asm.ClassVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.Playback;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.commons.EmptyVisitor;
@@ -33,19 +31,19 @@
*/
public class FieldStereotypeVisitor extends EmptyVisitor {
- private final FieldVisitor delegate;
- private final List<RootAnnotationRecorder> m_recorder;
+ private final FieldVisitor m_delegate;
+ private final AnnotationType m_annotationType;
- public FieldStereotypeVisitor(final FieldVisitor delegate, List<RootAnnotationRecorder> recorder) {
- this.delegate = delegate;
- m_recorder = recorder;
+ public FieldStereotypeVisitor(final FieldVisitor delegate, AnnotationType annotationType) {
+ this.m_delegate = delegate;
+ m_annotationType = annotationType;
}
@Override
public void visitEnd() {
// Replay stereotype annotations
- for (RootAnnotationRecorder recorder : m_recorder) {
- recorder.accept(delegate);
+ for (Playback playback : m_annotationType.getPlaybacks()) {
+ playback.accept(m_delegate);
}
}
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/MethodStereotypeVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/MethodStereotypeVisitor.java
index 06dc9af..f7f0bfd 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/MethodStereotypeVisitor.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/MethodStereotypeVisitor.java
@@ -19,10 +19,8 @@
package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype;
-import java.util.List;
-
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay.RootAnnotationRecorder;
-import org.objectweb.asm.FieldVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.Playback;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.EmptyVisitor;
@@ -33,19 +31,19 @@
*/
public class MethodStereotypeVisitor extends EmptyVisitor {
- private final MethodVisitor delegate;
- private final List<RootAnnotationRecorder> m_recorder;
+ private final MethodVisitor m_delegate;
+ private final AnnotationType m_annotationType;
- public MethodStereotypeVisitor(final MethodVisitor delegate, List<RootAnnotationRecorder> recorder) {
- this.delegate = delegate;
- m_recorder = recorder;
+ public MethodStereotypeVisitor(final MethodVisitor delegate, AnnotationType annotationType) {
+ this.m_delegate = delegate;
+ m_annotationType = annotationType;
}
@Override
public void visitEnd() {
// Replay stereotype annotations
- for (RootAnnotationRecorder recorder : m_recorder) {
- recorder.accept(delegate);
+ for (Playback playback : m_annotationType.getPlaybacks()) {
+ playback.accept(m_delegate);
}
}
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/ParameterStereotypeVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/ParameterStereotypeVisitor.java
index c764399..2c8beef 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/ParameterStereotypeVisitor.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/ParameterStereotypeVisitor.java
@@ -19,10 +19,8 @@
package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype;
-import java.util.List;
-
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay.RootAnnotationRecorder;
-import org.objectweb.asm.FieldVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.Playback;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.EmptyVisitor;
@@ -33,21 +31,21 @@
*/
public class ParameterStereotypeVisitor extends EmptyVisitor {
- private final MethodVisitor delegate;
+ private final MethodVisitor m_delegate;
private final int index;
- private final List<RootAnnotationRecorder> m_recorder;
+ private final AnnotationType m_annotationType;
- public ParameterStereotypeVisitor(final MethodVisitor delegate, final int index, List<RootAnnotationRecorder> recorder) {
- this.delegate = delegate;
+ public ParameterStereotypeVisitor(final MethodVisitor delegate, final int index, AnnotationType annotationType) {
+ this.m_delegate = delegate;
this.index = index;
- m_recorder = recorder;
+ m_annotationType = annotationType;
}
@Override
public void visitEnd() {
// Replay stereotype annotations
- for (RootAnnotationRecorder recorder : m_recorder) {
- recorder.accept(delegate, index);
+ for (Playback playback : m_annotationType.getPlaybacks()) {
+ playback.accept(m_delegate, index);
}
}
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/StereotypeVisitorFactory.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/StereotypeVisitorFactory.java
new file mode 100644
index 0000000..c6c7122
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/StereotypeVisitorFactory.java
@@ -0,0 +1,71 @@
+/*
+ * 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.manipulator.metadata.annotation.visitor.stereotype;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+* User: guillaume
+* Date: 11/07/13
+* Time: 14:26
+*/
+public class StereotypeVisitorFactory implements AnnotationVisitorFactory {
+ private final AnnotationType m_annotationType;
+
+ public StereotypeVisitorFactory(final AnnotationType annotationType) {
+ m_annotationType = annotationType;
+ }
+
+ public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+ if (context.getNode() instanceof ClassNode) {
+ return new TypeStereotypeVisitor((ClassVisitor) context.getVisitor(),
+ m_annotationType);
+ } else if (context.getNode() instanceof FieldNode) {
+ return new FieldStereotypeVisitor((FieldVisitor) context.getVisitor(),
+ m_annotationType);
+
+ } else if ((context.getNode() instanceof MethodNode) &&
+ (context.getParameterIndex() == BindingContext.NO_INDEX)) {
+ return new MethodStereotypeVisitor((MethodVisitor) context.getVisitor(),
+ m_annotationType);
+
+ } else {
+ // last case: method parameter annotation
+ return new ParameterStereotypeVisitor((MethodVisitor) context.getVisitor(),
+ context.getParameterIndex(),
+ m_annotationType);
+ }
+
+ }
+
+ @Override
+ public String toString() {
+ return "StereotypeVisitorFactory";
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/TypeStereotypeVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/TypeStereotypeVisitor.java
index 255219f..10493a1 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/TypeStereotypeVisitor.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/stereotype/TypeStereotypeVisitor.java
@@ -19,9 +19,8 @@
package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype;
-import java.util.List;
-
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay.RootAnnotationRecorder;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.Playback;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.commons.EmptyVisitor;
@@ -32,19 +31,19 @@
*/
public class TypeStereotypeVisitor extends EmptyVisitor {
- private final ClassVisitor delegate;
- private final List<RootAnnotationRecorder> m_recorder;
+ private final ClassVisitor m_delegate;
+ private final AnnotationType m_annotationType;
- public TypeStereotypeVisitor(final ClassVisitor delegate, List<RootAnnotationRecorder> recorder) {
- this.delegate = delegate;
- m_recorder = recorder;
+ public TypeStereotypeVisitor(final ClassVisitor delegate, AnnotationType annotationType) {
+ this.m_delegate = delegate;
+ m_annotationType = annotationType;
}
@Override
public void visitEnd() {
// Replay stereotype annotations
- for (RootAnnotationRecorder recorder : m_recorder) {
- recorder.accept(delegate);
+ for (Playback playback : m_annotationType.getPlaybacks()) {
+ playback.accept(m_delegate);
}
}
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java
index 3878190..2a74b87 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java
@@ -21,129 +21,31 @@
import org.apache.felix.ipojo.manipulator.Reporter;
import org.apache.felix.ipojo.manipulator.ResourceStore;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.AnnotationRegistry;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.StereotypeParser;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.DefaultBindingRegistry;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.IgnoreAllBindingRegistry;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.LegacyGenericBindingRegistry;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.MetaAnnotationBindingRegistry;
import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.BindingRegistry;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype.FieldStereotypeVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype.MethodStereotypeVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype.ParameterStereotypeVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype.TypeStereotypeVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.FieldGenericVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.MethodGenericVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.ParameterGenericVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.TypeGenericVisitor;
-import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
-import org.apache.felix.ipojo.manipulator.spi.BindingContext;
import org.apache.felix.ipojo.manipulator.spi.Module;
-import org.apache.felix.ipojo.manipulator.spi.Predicate;
-import org.apache.felix.ipojo.manipulator.util.Strings;
-import org.apache.felix.ipojo.metadata.Element;
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.tree.FieldNode;
-import org.objectweb.asm.tree.MethodNode;
-import java.io.IOException;
-import java.lang.annotation.ElementType;
-import java.util.ArrayList;
-import java.util.List;
import java.util.ServiceLoader;
-import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.and;
-import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.on;
import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.or;
-import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.pattern;
/**
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class Bindings {
- private static Binding newGenericTypeBinding() {
- Binding binding = new Binding();
- // ElementType is TYPE
- // Annotation descriptor is matching generic pattern
- binding.setPredicate(
- and(
- on(ElementType.TYPE),
- customAnnotationPattern()
- ));
- binding.setFactory(new AnnotationVisitorFactory() {
- public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
- Element element = Elements.buildElement(context.getAnnotationType());
- return new TypeGenericVisitor(context.getWorkbench(), element);
- }
- });
- return binding;
- }
-
- private static Predicate customAnnotationPattern() {
- return pattern("(.*\\.ipojo\\..*)|(.*\\.handler\\..*)").matches();
- }
-
- private static Binding newGenericFieldBinding() {
- Binding binding = new Binding();
- // ElementType is FIELD
- // Annotation descriptor is matching generic pattern
- binding.setPredicate(
- and(
- on(ElementType.FIELD),
- customAnnotationPattern()
- ));
- binding.setFactory(new AnnotationVisitorFactory() {
- public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
- Element element = Elements.buildElement(context.getAnnotationType());
- return new FieldGenericVisitor(context.getWorkbench(), element, (FieldNode) context.getNode());
- }
- });
- return binding;
- }
-
- private static Binding newGenericMethodBinding() {
- Binding binding = new Binding();
- // ElementType is METHOD
- // Annotation descriptor is matching generic pattern
- binding.setPredicate(
- and(
- on(ElementType.METHOD),
- customAnnotationPattern()
- ));
- binding.setFactory(new AnnotationVisitorFactory() {
- public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
- Element element = Elements.buildElement(context.getAnnotationType());
- return new MethodGenericVisitor(context.getWorkbench(), element, (MethodNode) context.getNode());
- }
- });
- return binding;
- }
-
- private static Binding newGenericParameterBinding() {
- Binding binding = new Binding();
- // ElementType is METHOD
- // Annotation descriptor is matching generic pattern
- binding.setPredicate(
- and(
- on(ElementType.PARAMETER),
- customAnnotationPattern()
- ));
- binding.setFactory(new AnnotationVisitorFactory() {
- public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
- Element element = Elements.buildElement(context.getAnnotationType());
- return new ParameterGenericVisitor(context.getWorkbench(), element, (MethodNode) context.getNode(), context.getParameterIndex());
- }
- });
- return binding;
- }
-
-
public static BindingRegistry newBindingRegistry(Reporter reporter, ResourceStore store) {
- AnnotationRegistry ar = new AnnotationRegistry();
- BindingRegistry registry = new BindingRegistry(reporter);
+ // Build the registry by aggregation of the features we want
+ // TODO We can enable/disable the legacy support easily here
+ BindingRegistry registry = new DefaultBindingRegistry(reporter);
+ registry = new MetaAnnotationBindingRegistry(registry, reporter, store);
+ registry = new LegacyGenericBindingRegistry(registry, reporter);
+ registry = new IgnoreAllBindingRegistry(registry, reporter);
+
ServiceLoader<Module> loader = ServiceLoader.load(Module.class, classloader());
// Build each Module and add its contributed Bindings in the registry
@@ -152,127 +54,9 @@
registry.addBindings(module);
}
- // Do not forget the default Bindings
- registry.getDefaultBindings().addAll(newDefaultBindings(store, ar));
-
return registry;
}
- public static List<Binding> newDefaultBindings(final ResourceStore store, final AnnotationRegistry ar) {
- List<Binding> bindings = new ArrayList<Binding>();
-
- // Register Stereotype binding support first
- // That allows iPOJO to provide its own stereotyped annotations
- bindings.add(newStereotypeTypeBinding(store, ar));
- bindings.add(newStereotypeFieldBinding(store, ar));
- bindings.add(newStereotypeMethodBinding(store, ar));
- bindings.add(newStereotypeParameterBinding(store, ar));
-
- // Then register the generic bindings
- bindings.add(newGenericTypeBinding());
- bindings.add(newGenericFieldBinding());
- bindings.add(newGenericMethodBinding());
- bindings.add(newGenericParameterBinding());
- return bindings;
-
- }
-
- private static Binding newStereotypeParameterBinding(final ResourceStore store, final AnnotationRegistry registry) {
- Binding binding = new Binding();
- binding.setPredicate(
- and(
- on(ElementType.PARAMETER),
- stereotype(store, registry)
- ));
- binding.setFactory(new AnnotationVisitorFactory() {
- public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
- return new ParameterStereotypeVisitor((MethodVisitor) context.getVisitor(),
- context.getParameterIndex(),
- registry.getRecorders(context.getAnnotationType()));
- }
- });
- return binding;
- }
-
- private static Binding newStereotypeMethodBinding(final ResourceStore store, final AnnotationRegistry registry) {
- Binding binding = new Binding();
- binding.setPredicate(
- and(
- on(ElementType.METHOD),
- stereotype(store, registry)
- ));
- binding.setFactory(new AnnotationVisitorFactory() {
- public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
- return new MethodStereotypeVisitor((MethodVisitor) context.getVisitor(),
- registry.getRecorders(context.getAnnotationType()));
- }
- });
- return binding;
- }
-
- private static Binding newStereotypeFieldBinding(final ResourceStore store, final AnnotationRegistry registry) {
- Binding binding = new Binding();
- binding.setPredicate(
- and(
- on(ElementType.FIELD),
- stereotype(store, registry)
- ));
- binding.setFactory(new AnnotationVisitorFactory() {
- public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
- return new FieldStereotypeVisitor((FieldVisitor) context.getVisitor(),
- registry.getRecorders(context.getAnnotationType()));
- }
- });
- return binding;
- }
-
- private static Binding newStereotypeTypeBinding(final ResourceStore store, final AnnotationRegistry registry) {
- Binding binding = new Binding();
- binding.setPredicate(
- and(
- on(ElementType.TYPE),
- stereotype(store, registry)
- ));
- binding.setFactory(new AnnotationVisitorFactory() {
- public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
- return new TypeStereotypeVisitor((ClassVisitor) context.getVisitor(),
- registry.getRecorders(context.getAnnotationType()));
- }
- });
- return binding;
- }
-
- private static Predicate stereotype(final ResourceStore store, final AnnotationRegistry registry) {
- return new Predicate() {
- public boolean matches(final BindingContext context) {
-
- Type type = context.getAnnotationType();
- if (registry.isUnknown(type)) {
- // The given annotation type was never parsed before
- try {
-
- // Try to read the annotation's byte code
- byte[] bytes = store.read(Strings.asResourcePath(context.getAnnotationType().getClassName()));
- StereotypeParser parser = new StereotypeParser();
- parser.read(bytes);
- if (parser.isStereotype()) {
- registry.addStereotype(type, parser.getRecorders());
- return true;
- }
- registry.addUnbound(type);
- return false;
- } catch (IOException e) {
- // Cannot load the byte code, assume it's not a stereotype
- // TODO print a warning ?
- registry.addUnbound(type);
- return false;
- }
- }
- return registry.isStereotype(type);
- }
- };
- }
-
private static ClassLoader classloader() {
return Bindings.class.getClassLoader();
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Elements.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Elements.java
index 28439b6..f9c2cc1 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Elements.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Elements.java
@@ -19,6 +19,8 @@
package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util;
+import static java.lang.String.format;
+
import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
import org.apache.felix.ipojo.metadata.Element;
import org.objectweb.asm.Type;
@@ -41,7 +43,38 @@
int index = name.lastIndexOf('.');
String local = name.substring(index + 1);
String namespace = name.substring(0, index);
- return new Element(local, namespace);
+ return buildElement(namespace, local);
+ }
+
+ /**
+ * Build an {@link Element} using the provided namespace and local name.
+ */
+ public static Element buildElement(final String namespace, final String name) {
+ return new Element(name, namespace);
+ }
+
+ /**
+ * Build an {@link Element} using the provided binding information.
+ * Expected format is {@literal [namespace:]name} (eg: {@literal com.acme:foo} or {@literal foo} if namespace
+ * by default -org.apache.felix.ipojo- has to be used).
+ * Notice that the ':' character usage in namespace or name part may lead to unexpected results.
+ * In that case, the @HandlerBinding(namespace = "urn:my:namespace", value = "foo:handler") usage is preferred.
+ * @param binding the condensed element name
+ * @return the new element
+ */
+ public static Element buildElement(String binding) {
+ String[] split = binding.split(":");
+ if (split.length == 1) {
+ return buildElement("", binding);
+ }
+ if (split.length > 2) {
+ throw new IllegalArgumentException(
+ format("@HandlerBinding(\"%s\") is invalid: only 1 ':' char is authorized, please" +
+ " use the @HandlerBinding(namespace=\"...\", value=\"...\") form instead.",
+ binding)
+ );
+ }
+ return buildElement(split[0], split[1]);
}
/**
@@ -52,7 +85,7 @@
public static Element getPropertiesElement(ComponentWorkbench workbench) {
Element properties = workbench.getIds().get("properties");
if (properties == null) {
- properties = new Element("properties", "");
+ properties = buildElement("", "properties");
workbench.getIds().put("properties", properties);
workbench.getElements().put(properties, null);
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java
index 7a1f1c7..c188e5e 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java
@@ -19,21 +19,23 @@
package org.apache.felix.ipojo.manipulator.spi;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.onlySupportedElements;
import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.alwaysTrue;
-import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.on;
-import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.onlySupportedElements;
-import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.or;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.AnnotationLiteral;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.AnnotationPlayback;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.GenericVisitorFactory;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ignore.NullBinding;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype.StereotypeVisitorFactory;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Elements;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.Type;
/**
* All provided {@link Module}s have to inherit from this class.
@@ -66,6 +68,18 @@
return new AnnotationBindingBuilder(bindings, annotationType);
}
+ protected StereotypeBindingBuilder bindStereotype(Class<? extends Annotation> annotationType) {
+ return new StereotypeBindingBuilder(bindings, annotationType);
+ }
+
+ protected HandlerBindingBuilder bindHandlerBinding(Class<? extends Annotation> annotationType) {
+ return new HandlerBindingBuilder(bindings, annotationType);
+ }
+
+ protected void bindIgnore(Class<? extends Annotation> annotationType) {
+ bindings.add(new NullBinding(Type.getType(annotationType)));
+ }
+
/**
* DSL helper class.
*/
@@ -104,7 +118,7 @@
*/
private Binding build() {
Binding binding = new Binding();
- binding.setAnnotationType(annotationType);
+ binding.setAnnotationType(Type.getType(annotationType));
binding.setPredicate(onlySupportedElements(annotationType));
binding.setFactory(factory);
return binding;
@@ -145,4 +159,40 @@
}
}
+ public class StereotypeBindingBuilder {
+ private final AnnotationType m_annotationType;
+
+ public StereotypeBindingBuilder(final List<Binding> bindings, final Class<? extends Annotation> type) {
+ m_annotationType = new AnnotationType(Type.getType(type));
+ Binding binding = new Binding();
+ binding.setAnnotationType(m_annotationType.getType());
+ binding.setPredicate(onlySupportedElements(type));
+ binding.setFactory(new StereotypeVisitorFactory(m_annotationType));
+ bindings.add(binding);
+ }
+
+ public StereotypeBindingBuilder with(AnnotationLiteral<?> literal) {
+ m_annotationType.getPlaybacks().add(new AnnotationPlayback(literal));
+ return this;
+ }
+ }
+
+ public class HandlerBindingBuilder {
+
+ private final Binding m_binding;
+
+ public HandlerBindingBuilder(final List<Binding> bindings, final Class<? extends Annotation> annotationType) {
+ m_binding = new Binding();
+ Type type = Type.getType(annotationType);
+ m_binding.setAnnotationType(type);
+ m_binding.setPredicate(onlySupportedElements(annotationType));
+ Element e = Elements.buildElement(type);
+ m_binding.setFactory(new GenericVisitorFactory(e.getName(), e.getNameSpace()));
+ bindings.add(m_binding);
+ }
+
+ public void to(String namespace, String name) {
+ m_binding.setFactory(new GenericVisitorFactory(name, namespace));
+ }
+ }
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java
index 72bdc25..316345c 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java
@@ -31,6 +31,8 @@
*/
public class BindingContext {
+ public static final int NO_INDEX = -1;
+
/**
*
*/
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/ChainedAnnotationVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/ChainedAnnotationVisitor.java
new file mode 100644
index 0000000..cf138da
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/ChainedAnnotationVisitor.java
@@ -0,0 +1,88 @@
+/*
+ * 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.manipulator.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.discovery.ChainedAnnotationDiscovery;
+import org.objectweb.asm.AnnotationVisitor;
+
+/**
+* User: guillaume
+* Date: 10/07/13
+* Time: 16:43
+*/
+public class ChainedAnnotationVisitor implements AnnotationVisitor {
+
+ private List<AnnotationVisitor> m_visitors = new ArrayList<AnnotationVisitor>();
+
+ public List<AnnotationVisitor> getVisitors() {
+ return m_visitors;
+ }
+
+ public void visit(final String name, final Object value) {
+ for (AnnotationVisitor visitor : m_visitors) {
+ visitor.visit(name, value);
+ }
+ }
+
+ public void visitEnum(final String name, final String desc, final String value) {
+ for (AnnotationVisitor visitor : m_visitors) {
+ visitor.visitEnum(name, desc, value);
+ }
+ }
+
+ public AnnotationVisitor visitAnnotation(final String name, final String desc) {
+ ChainedAnnotationVisitor chain = null;
+ for (AnnotationVisitor visitor : m_visitors) {
+ AnnotationVisitor child = visitor.visitAnnotation(name, desc);
+ if (child != null) {
+ if (chain == null) {
+ chain = new ChainedAnnotationVisitor();
+ }
+ chain.getVisitors().add(child);
+ }
+
+ }
+ return chain;
+ }
+
+ public AnnotationVisitor visitArray(final String name) {
+ ChainedAnnotationVisitor chain = null;
+ for (AnnotationVisitor visitor : m_visitors) {
+ AnnotationVisitor child = visitor.visitArray(name);
+ if (child != null) {
+ if (chain == null) {
+ chain = new ChainedAnnotationVisitor();
+ }
+ chain.getVisitors().add(child);
+ }
+
+ }
+ return chain;
+ }
+
+ public void visitEnd() {
+ for (AnnotationVisitor visitor : m_visitors) {
+ visitor.visitEnd();
+ }
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/AnnotationMetadataProviderTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/AnnotationMetadataProviderTestCase.java
index 5570eb6..d469495 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/AnnotationMetadataProviderTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/AnnotationMetadataProviderTestCase.java
@@ -63,7 +63,11 @@
}
public byte[] read(String path) throws IOException {
- return resources.get(path);
+ byte[] bytes = resources.get(path);
+ if (bytes == null) {
+ throw new IOException();
+ }
+ return bytes;
}
public void accept(ResourceVisitor visitor) {
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteralTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteralTestCase.java
new file mode 100644
index 0000000..9d6360d
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteralTestCase.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.manipulator.metadata.annotation.model.literal;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.AnnotationLiteral;
+
+import junit.framework.TestCase;
+
+/**
+ * User: guillaume
+ * Date: 28/06/13
+ * Time: 14:40
+ */
+public class AnnotationLiteralTestCase extends TestCase {
+ public void testAnnotationTypeDiscovery() throws Exception {
+
+ FooLiteral fooLiteral = new FooLiteral() {
+ public String value() {
+ return "a";
+ }
+ };
+
+ assertEquals(Foo.class, fooLiteral.annotationType());
+ assertEquals("a", fooLiteral.value());
+
+ }
+
+ private static abstract class FooLiteral extends AnnotationLiteral<Foo> implements Foo { }
+
+ private static @interface Foo {
+ String value();
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationPlaybackTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationPlaybackTestCase.java
new file mode 100644
index 0000000..05c1c68
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationPlaybackTestCase.java
@@ -0,0 +1,196 @@
+/*
+ * 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.manipulator.metadata.annotation.model.literal;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.AnnotationPlayback;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types.AnnotationAnnotation;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types.ArrayAnnotation;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types.EnumAnnotation;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types.InnerAnnotation;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types.Mode;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types.SimpleTypes;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types.Support;
+import org.mockito.Mock;
+
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.mockito.MockitoAnnotations;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Type;
+
+import junit.framework.TestCase;
+
+/**
+ * User: guillaume
+ * Date: 08/07/13
+ * Time: 17:25
+ */
+
+public class AnnotationPlaybackTestCase extends TestCase {
+
+ @Mock
+ private ClassVisitor visitor;
+
+ @Mock
+ private AnnotationVisitor annotationVisitor;
+
+ @Mock
+ private AnnotationVisitor arrayVisitor;
+
+ @Mock
+ private AnnotationVisitor innerAnnotationVisitor;
+
+ @Override
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ public void testSimpleValuesPlayback() throws Exception {
+
+ when(visitor.visitAnnotation(anyString(), anyBoolean())).thenReturn(annotationVisitor);
+
+ AnnotationPlayback playback = new AnnotationPlayback(find(SimpleTypes.class));
+ playback.accept(visitor);
+
+ verify(visitor).visitAnnotation(Type.getType(SimpleTypes.class).getDescriptor(),
+ true);
+ verify(annotationVisitor).visitEnd();
+
+ // Verify simple mono-valued attributes
+ verify(annotationVisitor).visit("aByte", Byte.valueOf((byte) 42));
+ verify(annotationVisitor).visit("aBoolean", Boolean.TRUE);
+ verify(annotationVisitor).visit("anInt", Integer.valueOf(42));
+ verify(annotationVisitor).visit("aLong", Long.valueOf(42));
+ verify(annotationVisitor).visit("aShort", Short.valueOf((short) 42));
+ verify(annotationVisitor).visit("aFloat", Float.valueOf(42));
+ verify(annotationVisitor).visit("aDouble", Double.valueOf(42));
+ verify(annotationVisitor).visit("aChar", Character.valueOf('a'));
+
+ // Verify String & Class
+ verify(annotationVisitor).visit("aString", "42");
+ verify(annotationVisitor).visit("aClass", Type.getType(String.class));
+
+ // Verify array os simple types
+ verify(annotationVisitor).visit("arrayOfByte", new byte[] {(byte) 42});
+ verify(annotationVisitor).visit("arrayOfBoolean", new boolean[] {true, true});
+ verify(annotationVisitor).visit("arrayOfInt", new int[] {42});
+ verify(annotationVisitor).visit("arrayOfLong", new long[] {42});
+ verify(annotationVisitor).visit("arrayOfShort", new short[] {42});
+ verify(annotationVisitor).visit("arrayOfFloat", new float[] {42});
+ verify(annotationVisitor).visit("arrayOfDouble", new double[] {});
+ verify(annotationVisitor).visit("arrayOfChar", new char[] {'a', 'b', 'c'});
+
+ }
+
+ public void testEnumValuesPlayback() throws Exception {
+
+ when(visitor.visitAnnotation(anyString(), anyBoolean())).thenReturn(annotationVisitor);
+
+ AnnotationPlayback playback = new AnnotationPlayback(find(EnumAnnotation.class));
+ playback.accept(visitor);
+
+ verify(visitor).visitAnnotation(Type.getType(EnumAnnotation.class).getDescriptor(),
+ true);
+ verify(annotationVisitor).visitEnd();
+
+ String desc = Type.getType(Mode.class).getDescriptor();
+ verify(annotationVisitor).visitEnum("noDefault", desc, "IN");
+ verify(annotationVisitor).visitEnum("withDefault", desc, "IN");
+ verify(annotationVisitor).visitEnum("withDefaultOverridden", desc, "IN");
+ }
+
+ public void testArrayValuesPlayback() throws Exception {
+
+ AnnotationVisitor arrayOfString = mock(AnnotationVisitor.class);
+ AnnotationVisitor arrayOfEnum = mock(AnnotationVisitor.class);
+ AnnotationVisitor arrayOfClass = mock(AnnotationVisitor.class);
+ AnnotationVisitor arrayOfAnnotation = mock(AnnotationVisitor.class);
+ AnnotationVisitor emptyArray = mock(AnnotationVisitor.class);
+
+ when(visitor.visitAnnotation(anyString(), anyBoolean())).thenReturn(annotationVisitor);
+ when(annotationVisitor.visitArray("arrayOfString")).thenReturn(arrayOfString);
+ when(annotationVisitor.visitArray("arrayOfEnum")).thenReturn(arrayOfEnum);
+ when(annotationVisitor.visitArray("arrayOfClass")).thenReturn(arrayOfClass);
+ when(annotationVisitor.visitArray("arrayOfAnnotation")).thenReturn(arrayOfAnnotation);
+ when(annotationVisitor.visitArray("emptyArray")).thenReturn(emptyArray);
+
+ AnnotationPlayback playback = new AnnotationPlayback(find(ArrayAnnotation.class));
+ playback.accept(visitor);
+
+ verify(visitor).visitAnnotation(Type.getType(ArrayAnnotation.class).getDescriptor(),
+ true);
+ verify(annotationVisitor).visitEnd();
+
+ String desc = Type.getType(Mode.class).getDescriptor();
+
+ verify(arrayOfString).visit(null, "42");
+ verify(arrayOfString).visit(null, "43");
+ verify(arrayOfString).visitEnd();
+
+ verify(arrayOfEnum).visitEnum(null, desc, "IN");
+ verify(arrayOfEnum).visitEnd();
+
+ verify(arrayOfClass).visit(null, Type.getType(Object.class));
+ verify(arrayOfClass).visitEnd();
+
+ verify(arrayOfAnnotation).visitAnnotation(null, Type.getType(InnerAnnotation.class).getDescriptor());
+ verify(arrayOfAnnotation).visitEnd();
+
+ verify(emptyArray).visitEnd();
+
+ }
+
+
+ public void testAnnotationValuesPlayback() throws Exception {
+
+ when(visitor.visitAnnotation(anyString(), anyBoolean())).thenReturn(annotationVisitor);
+ when(annotationVisitor.visitAnnotation("value", Type.getType(InnerAnnotation.class).getDescriptor()))
+ .thenReturn(innerAnnotationVisitor);
+ when(innerAnnotationVisitor.visitArray("arrayOfClass"))
+ .thenReturn(arrayVisitor);
+
+ AnnotationPlayback playback = new AnnotationPlayback(find(AnnotationAnnotation.class));
+ playback.accept(visitor);
+
+ verify(visitor).visitAnnotation(Type.getType(AnnotationAnnotation.class).getDescriptor(),
+ true);
+ verify(annotationVisitor).visitEnd();
+
+ String desc = Type.getType(Mode.class).getDescriptor();
+ verify(innerAnnotationVisitor).visit("aString", "42");
+ verify(innerAnnotationVisitor).visitEnum("modeEnum", desc, "IN");
+ verify(innerAnnotationVisitor).visitEnd();
+
+ verify(arrayVisitor).visit(null, Type.getType(Object.class));
+ verify(arrayVisitor).visitEnd();
+
+ }
+ private Annotation find(final Class<? extends Annotation> type) {
+ return Support.class.getAnnotation(type);
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/AnnotationAnnotation.java
similarity index 64%
copy from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
copy to ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/AnnotationAnnotation.java
index 1748cfc..c707d7d 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/AnnotationAnnotation.java
@@ -17,15 +17,20 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types;
-import org.objectweb.asm.AnnotationVisitor;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
-* User: guillaume
-* Date: 30/05/13
-* Time: 17:23
-*/
-public interface Replay {
- void accept(AnnotationVisitor visitor);
+ * User: guillaume
+ * Date: 09/07/13
+ * Time: 10:15
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnnotationAnnotation {
+ InnerAnnotation value();
}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/ArrayAnnotation.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/ArrayAnnotation.java
new file mode 100644
index 0000000..92bee87
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/ArrayAnnotation.java
@@ -0,0 +1,40 @@
+/*
+ * 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.manipulator.metadata.annotation.model.literal.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * User: guillaume
+ * Date: 09/07/13
+ * Time: 10:15
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ArrayAnnotation {
+ String[] arrayOfString();
+ Class<?>[] arrayOfClass();
+ Mode[] arrayOfEnum();
+ InnerAnnotation[] arrayOfAnnotation();
+ Mode[] emptyArray() default {};
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/EnumAnnotation.java
similarity index 61%
copy from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
copy to ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/EnumAnnotation.java
index 1748cfc..9ec1a4a 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/EnumAnnotation.java
@@ -17,15 +17,22 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types;
-import org.objectweb.asm.AnnotationVisitor;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
-* User: guillaume
-* Date: 30/05/13
-* Time: 17:23
-*/
-public interface Replay {
- void accept(AnnotationVisitor visitor);
+ * User: guillaume
+ * Date: 09/07/13
+ * Time: 10:15
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface EnumAnnotation {
+ Mode noDefault();
+ Mode withDefault() default Mode.IN;
+ Mode withDefaultOverridden() default Mode.OUT;
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/InnerAnnotation.java
similarity index 62%
copy from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
copy to ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/InnerAnnotation.java
index 1748cfc..4bdfbd7 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/InnerAnnotation.java
@@ -17,15 +17,21 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types;
-import org.objectweb.asm.AnnotationVisitor;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
-* User: guillaume
-* Date: 30/05/13
-* Time: 17:23
-*/
-public interface Replay {
- void accept(AnnotationVisitor visitor);
+ * User: guillaume
+ * Date: 09/07/13
+ * Time: 10:15
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface InnerAnnotation {
+ String aString() default "42";
+ Class[] arrayOfClass() default {};
+ Mode modeEnum() default Mode.IN;
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/Mode.java
similarity index 76%
copy from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
copy to ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/Mode.java
index 1748cfc..dec0af2 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/Replay.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/Mode.java
@@ -17,15 +17,13 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
-
-import org.objectweb.asm.AnnotationVisitor;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.types;
/**
-* User: guillaume
-* Date: 30/05/13
-* Time: 17:23
-*/
-public interface Replay {
- void accept(AnnotationVisitor visitor);
+ * User: guillaume
+ * Date: 09/07/13
+ * Time: 10:14
+ */
+public enum Mode {
+ IN, OUT
}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/SimpleTypes.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/SimpleTypes.java
new file mode 100644
index 0000000..c592962
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/SimpleTypes.java
@@ -0,0 +1,56 @@
+/*
+ * 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.manipulator.metadata.annotation.model.literal.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+* User: guillaume
+* Date: 08/07/13
+* Time: 17:37
+*/
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SimpleTypes {
+ boolean aBoolean() default true;
+ byte aByte() default 42;
+ long aLong() default 42;
+ int anInt() default 42;
+ short aShort() default 42;
+ float aFloat() default 42;
+ double aDouble() default 42;
+ char aChar() default 'a';
+
+ String aString() default "42";
+ Class<?> aClass() default String.class;
+
+ boolean[] arrayOfBoolean() default {true, true};
+ byte[] arrayOfByte() default {42};
+ long[] arrayOfLong() default {42};
+ int[] arrayOfInt() default {42};
+ short[] arrayOfShort() default {42};
+ float[] arrayOfFloat() default 42;
+ double[] arrayOfDouble() default {};
+ char[] arrayOfChar() default {'a', 'b', 'c'};
+
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/Support.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/Support.java
new file mode 100644
index 0000000..3c2bee6
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/types/Support.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.manipulator.metadata.annotation.model.literal.types;
+
+/**
+ * User: guillaume
+ * Date: 08/07/13
+ * Time: 17:36
+ */
+@SimpleTypes
+@EnumAnnotation(
+ noDefault = Mode.IN,
+ withDefaultOverridden = Mode.IN
+)
+@ArrayAnnotation(
+ arrayOfString = {"42", "43"},
+ arrayOfEnum = Mode.IN,
+ arrayOfClass = Object.class,
+ arrayOfAnnotation = @InnerAnnotation()
+)
+@AnnotationAnnotation(
+ @InnerAnnotation(
+ arrayOfClass = Object.class
+ )
+)
+public class Support {
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/AnnotationRecorderTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/AnnotationRecorderTestCase.java
similarity index 96%
rename from ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/AnnotationRecorderTestCase.java
rename to ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/AnnotationRecorderTestCase.java
index 71e5058..fdd9244 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/replay/AnnotationRecorderTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/parser/replay/AnnotationRecorderTestCase.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay;
+package org.apache.felix.ipojo.manipulator.metadata.annotation.model.parser.replay;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/AnnotationRegistryTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/AnnotationRegistryTestCase.java
deleted file mode 100644
index 1607589..0000000
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/AnnotationRegistryTestCase.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.manipulator.metadata.annotation.registry;
-
-import java.util.Collections;
-
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay.RootAnnotationRecorder;
-import org.objectweb.asm.Type;
-
-import junit.framework.TestCase;
-
-/**
- * User: guillaume
- * Date: 31/05/13
- * Time: 00:18
- */
-public class AnnotationRegistryTestCase extends TestCase {
- public void testEmptyRegistry() throws Exception {
- AnnotationRegistry registry = new AnnotationRegistry();
- assertTrue(registry.isUnknown(Type.BOOLEAN_TYPE));
- assertFalse(registry.isStereotype(Type.BOOLEAN_TYPE));
- assertFalse(registry.isUnbound(Type.BOOLEAN_TYPE));
- }
-
- public void testRegistry1() throws Exception {
- AnnotationRegistry registry = new AnnotationRegistry();
- registry.addStereotype(Type.BOOLEAN_TYPE, Collections.<RootAnnotationRecorder>emptyList());
-
- assertFalse(registry.isUnknown(Type.BOOLEAN_TYPE));
- assertTrue(registry.isStereotype(Type.BOOLEAN_TYPE));
- assertFalse(registry.isUnbound(Type.BOOLEAN_TYPE));
- }
-
- public void testRegistry2() throws Exception {
- AnnotationRegistry registry = new AnnotationRegistry();
- registry.addUnbound(Type.BOOLEAN_TYPE);
-
- assertFalse(registry.isUnknown(Type.BOOLEAN_TYPE));
- assertFalse(registry.isStereotype(Type.BOOLEAN_TYPE));
- assertTrue(registry.isUnbound(Type.BOOLEAN_TYPE));
- }
-}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/CompletableBindingRegistryTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/CompletableBindingRegistryTestCase.java
new file mode 100644
index 0000000..9ff6a5a
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/CompletableBindingRegistryTestCase.java
@@ -0,0 +1,83 @@
+/*
+ * 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.manipulator.metadata.annotation.registry;
+
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ignore.NullBinding;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.objectweb.asm.Type;
+
+import junit.framework.TestCase;
+
+/**
+ * User: guillaume
+ * Date: 12/07/13
+ * Time: 10:27
+ */
+public class CompletableBindingRegistryTestCase extends TestCase {
+
+ public static final String DESCRIPTOR = "[unknown;";
+
+ @Mock
+ private BindingRegistry delegate;
+
+ @Override
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ public void testUnknownDescriptorTriggerCallback() throws Exception {
+ EmptyCompletableBindingRegistry registry = new EmptyCompletableBindingRegistry(delegate);
+ when(delegate.getBindings(DESCRIPTOR)).thenReturn(Collections.<Binding>emptyList());
+
+ registry.getBindings(DESCRIPTOR);
+
+ assertNotNull(registry.type);
+ }
+
+ public void testKnownDescriptorDoNotTriggerCallback() throws Exception {
+ EmptyCompletableBindingRegistry registry = new EmptyCompletableBindingRegistry(delegate);
+ when(delegate.getBindings(DESCRIPTOR)).thenReturn(Collections.<Binding>singletonList(new NullBinding(Type.getType(DESCRIPTOR))));
+
+ registry.getBindings(DESCRIPTOR);
+
+ assertNull(registry.type);
+ }
+
+ private static class EmptyCompletableBindingRegistry extends CompletableBindingRegistry {
+
+ public Type type = null;
+
+ public EmptyCompletableBindingRegistry(final BindingRegistry delegate) {
+ super(delegate, null);
+ }
+
+ @Override
+ protected List<Binding> createBindings(final Type type) {
+ this.type = type;
+ return Collections.emptyList();
+ }
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/DefaultBindingRegistryTestCase.java
similarity index 88%
rename from ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java
rename to ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/DefaultBindingRegistryTestCase.java
index 7c1bbf4..5495929 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/DefaultBindingRegistryTestCase.java
@@ -38,8 +38,9 @@
* Time: 10:31 AM
* To change this template use File | Settings | File Templates.
*/
-public class BindingRegistryTestCase extends TestCase {
+public class DefaultBindingRegistryTestCase extends TestCase {
+ public static final Type PROVIDES_TYPE = Type.getType(Provides.class);
private BindingRegistry registry;
@Mock
@@ -52,7 +53,7 @@
@Override
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- registry = new BindingRegistry(reporter);
+ registry = new DefaultBindingRegistry(reporter);
}
public void testBindingAddition() throws Exception {
@@ -68,13 +69,12 @@
}
public void testGetBindingsWhenEmpty() throws Exception {
- assertNull(registry.getBindings(Type.getType(Provides.class).getDescriptor()));
- assertNotNull(registry.selection(null));
+ assertTrue(registry.getBindings(PROVIDES_TYPE.getDescriptor()).isEmpty());
}
private Binding binding() {
Binding binding = new Binding();
- binding.setAnnotationType(Provides.class);
+ binding.setAnnotationType(PROVIDES_TYPE);
binding.setFactory(factory);
binding.setPredicate(predicate);
return binding;
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/IgnoreAllBindingRegistryTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/IgnoreAllBindingRegistryTestCase.java
new file mode 100644
index 0000000..d06fda9
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/IgnoreAllBindingRegistryTestCase.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.registry;
+
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ignore.NullBinding;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import junit.framework.TestCase;
+
+/**
+ * User: guillaume
+ * Date: 11/07/13
+ * Time: 17:36
+ */
+public class IgnoreAllBindingRegistryTestCase extends TestCase {
+ public static final String UNKNOWN_DESCRIPTOR = "[unknown;";
+
+ @Mock
+ private BindingRegistry delegate;
+
+ @Override
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ public void testThatNullBindingIsGenerated() throws Exception {
+ when(delegate.getBindings(UNKNOWN_DESCRIPTOR)).thenReturn(Collections.<Binding>emptyList());
+
+ IgnoreAllBindingRegistry registry = new IgnoreAllBindingRegistry(delegate, null);
+
+ List<Binding> bindings = registry.getBindings(UNKNOWN_DESCRIPTOR);
+ assertTrue(bindings.get(0) instanceof NullBinding);
+
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/LegacyGenericBindingRegistryTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/LegacyGenericBindingRegistryTestCase.java
new file mode 100644
index 0000000..1dbdd14
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/LegacyGenericBindingRegistryTestCase.java
@@ -0,0 +1,95 @@
+/*
+ * 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.manipulator.metadata.annotation.registry;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.objectweb.asm.Type;
+
+import junit.framework.TestCase;
+
+/**
+ * User: guillaume
+ * Date: 11/07/13
+ * Time: 17:07
+ */
+public class LegacyGenericBindingRegistryTestCase extends TestCase {
+
+ public static final String AN_IGNORED_ANNOTATION = "[an.ignored.Annotation;";
+ public static final String RECOGNISED_IPOJO_ANNOTATION = "[a.recognised.ipojo.Annotation;";
+ public static final String RECOGNISED_HANDLER_ANNOTATION = "[a.recognised.handler.Annotation;";
+
+ @Mock
+ private BindingRegistry delegate;
+
+ @Captor
+ ArgumentCaptor<List<Binding>> capture;
+
+ @Override
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ public void testNonRecognisedTypeAreIgnored() throws Exception {
+ when(delegate.getBindings(AN_IGNORED_ANNOTATION)).thenReturn(Collections.<Binding>emptyList());
+
+ LegacyGenericBindingRegistry registry = new LegacyGenericBindingRegistry(delegate, null);
+
+ List<Binding> bindings = registry.getBindings(AN_IGNORED_ANNOTATION);
+ assertTrue(bindings.isEmpty());
+
+ verify(delegate).addBindings(capture.capture());
+ assertTrue(capture.getValue().isEmpty());
+ }
+
+ public void testIPojoRecognisedTypeAreSupported() throws Exception {
+ when(delegate.getBindings(RECOGNISED_IPOJO_ANNOTATION)).thenReturn(Collections.<Binding>emptyList());
+
+ LegacyGenericBindingRegistry registry = new LegacyGenericBindingRegistry(delegate, null);
+
+ List<Binding> bindings = registry.getBindings(RECOGNISED_IPOJO_ANNOTATION);
+ assertEquals(1, bindings.size());
+
+ verify(delegate).addBindings(capture.capture());
+ Binding one = capture.getValue().get(0);
+ assertEquals(Type.getType(RECOGNISED_IPOJO_ANNOTATION), one.getAnnotationType());
+ }
+
+ public void testHandlerRecognisedTypeAreSupported() throws Exception {
+ when(delegate.getBindings(RECOGNISED_HANDLER_ANNOTATION)).thenReturn(Collections.<Binding>emptyList());
+
+ LegacyGenericBindingRegistry registry = new LegacyGenericBindingRegistry(delegate, null);
+
+ List<Binding> bindings = registry.getBindings(RECOGNISED_HANDLER_ANNOTATION);
+ assertEquals(1, bindings.size());
+
+ verify(delegate).addBindings(capture.capture());
+ Binding one = capture.getValue().get(0);
+ assertEquals(Type.getType(RECOGNISED_HANDLER_ANNOTATION), one.getAnnotationType());
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/MetaAnnotationBindingRegistryTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/MetaAnnotationBindingRegistryTestCase.java
new file mode 100644
index 0000000..4e05111
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/MetaAnnotationBindingRegistryTestCase.java
@@ -0,0 +1,174 @@
+/*
+ * 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.manipulator.metadata.annotation.registry;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.HandlerBinding;
+import org.apache.felix.ipojo.annotations.Ignore;
+import org.apache.felix.ipojo.annotations.Stereotype;
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.ResourceStore;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.GenericVisitorFactory;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ignore.NullBinding;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ignore.NullVisitorFactory;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype.StereotypeVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.util.Streams;
+import org.apache.felix.ipojo.manipulator.util.Strings;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.objectweb.asm.Type;
+
+import junit.framework.TestCase;
+
+/**
+ * User: guillaume
+ * Date: 12/07/13
+ * Time: 12:13
+ */
+public class MetaAnnotationBindingRegistryTestCase extends TestCase {
+
+ public static final String DESCRIPTOR = "[unknown;";
+ public static final Type TYPE = Type.getType(DESCRIPTOR);
+
+ @Mock
+ private BindingRegistry delegate;
+
+ @Mock
+ private ResourceStore store;
+
+ @Mock
+ private Reporter reporter;
+
+ @Override
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(delegate.getBindings(DESCRIPTOR)).thenReturn(Collections.<Binding>emptyList());
+ }
+
+ public void testAnnotationTypeResourceNotFound() throws Exception {
+ when(store.read(anyString()))
+ .thenThrow(IOException.class);
+ MetaAnnotationBindingRegistry registry = new MetaAnnotationBindingRegistry(delegate, reporter, store);
+ assertTrue(registry.getBindings(DESCRIPTOR).isEmpty());
+ }
+
+ public void testClassicalAnnotation() throws Exception {
+ when(store.read(anyString()))
+ .thenReturn(from(Classical.class));
+ MetaAnnotationBindingRegistry registry = new MetaAnnotationBindingRegistry(delegate, reporter, store);
+ assertTrue(registry.getBindings(Type.getDescriptor(Classical.class)).isEmpty());
+ }
+
+ public void testStereotypeAnnotation() throws Exception {
+ when(store.read(anyString()))
+ .thenReturn(from(Stereotyped.class));
+ MetaAnnotationBindingRegistry registry = new MetaAnnotationBindingRegistry(delegate, reporter, store);
+ Binding binding = registry.getBindings(Type.getDescriptor(Stereotyped.class)).get(0);
+ assertTrue(binding.getFactory() instanceof StereotypeVisitorFactory);
+ }
+
+ public void testHandlerBindingAnnotation() throws Exception {
+ when(store.read(anyString()))
+ .thenReturn(from(Bound.class));
+ MetaAnnotationBindingRegistry registry = new MetaAnnotationBindingRegistry(delegate, reporter, store);
+ Binding binding = registry.getBindings(Type.getDescriptor(Bound.class)).get(0);
+ assertTrue(binding.getFactory() instanceof GenericVisitorFactory);
+ }
+
+ public void testIgnoreAnnotation() throws Exception {
+ when(store.read(anyString()))
+ .thenReturn(from(Ignored.class));
+ MetaAnnotationBindingRegistry registry = new MetaAnnotationBindingRegistry(delegate, reporter, store);
+ Binding binding = registry.getBindings(Type.getDescriptor(Ignored.class)).get(0);
+ assertTrue(binding instanceof NullBinding);
+ }
+
+ public void testBothStereotypeAndBindingAnnotation() throws Exception {
+ when(store.read(anyString()))
+ .thenReturn(from(StereotypedBinding.class));
+ MetaAnnotationBindingRegistry registry = new MetaAnnotationBindingRegistry(delegate, reporter, store);
+ List<Binding> bindings = registry.getBindings(Type.getDescriptor(StereotypedBinding.class));
+ assertEquals(2, bindings.size());
+ assertHasVisitorFactories(bindings, StereotypeVisitorFactory.class, GenericVisitorFactory.class);
+ }
+
+ public void testIgnoredWithStereotypeAnnotation() throws Exception {
+ when(store.read(anyString()))
+ .thenReturn(from(StereotypedIgnoredBinding.class));
+ MetaAnnotationBindingRegistry registry = new MetaAnnotationBindingRegistry(delegate, reporter, store);
+ List<Binding> bindings = registry.getBindings(Type.getDescriptor(StereotypedIgnoredBinding.class));
+ assertEquals(1, bindings.size());
+ assertHasVisitorFactories(bindings, NullVisitorFactory.class);
+ }
+
+ private void assertHasVisitorFactories(final List<Binding> bindings,
+ final Class<? extends AnnotationVisitorFactory>... factories) {
+ List<Class<? extends AnnotationVisitorFactory>> existing = new ArrayList<Class<? extends AnnotationVisitorFactory>>();
+ for (Binding binding : bindings) {
+ existing.add(binding.getFactory().getClass());
+ }
+
+ for (Class<? extends AnnotationVisitorFactory> factory : factories) {
+ if (!existing.remove(factory)) {
+ fail("Bindings do not contains expected AnnotationVisitorFactory type: " + factory.getName());
+ }
+ }
+ }
+
+ private byte[] from(Class<?> type) throws IOException {
+ ClassLoader loader = type.getClassLoader();
+ InputStream is = loader.getResourceAsStream(Strings.asResourcePath(type.getName()));
+ return Streams.readBytes(is);
+ }
+
+ private static @interface Classical {}
+
+ @Component
+ @Stereotype
+ private static @interface Stereotyped {}
+
+ @HandlerBinding
+ private static @interface Bound {}
+
+ @Ignore
+ private static @interface Ignored {}
+
+ @Component
+ @Stereotype
+ @HandlerBinding
+ private static @interface StereotypedBinding {}
+
+ @Component
+ @Stereotype
+ @HandlerBinding
+ @Ignore
+ private static @interface StereotypedIgnoredBinding {}
+
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java
index d1def40..06c337d 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java
@@ -22,11 +22,6 @@
import junit.framework.TestCase;
import org.apache.felix.ipojo.manipulator.Reporter;
import org.apache.felix.ipojo.manipulator.ResourceStore;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.FieldGenericVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.MethodGenericVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.ParameterGenericVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.TypeGenericVisitor;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Bindings;
import org.apache.felix.ipojo.manipulator.spi.AbsBindingModule;
import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
import org.apache.felix.ipojo.manipulator.spi.BindingContext;
@@ -45,7 +40,6 @@
import java.lang.annotation.Target;
import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
@@ -73,7 +67,7 @@
@Override
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- registry = new BindingRegistry(reporter);
+ registry = new DefaultBindingRegistry(reporter);
when(factory.newAnnotationVisitor(any(BindingContext.class)))
.thenReturn(visitor);
// Simulate a resource not found exception
@@ -150,23 +144,6 @@
}
- public void testSelectionForGenericVisitors() throws Exception {
-
- assertClassSelection(OnTypeOnly.class, nullValue());
- assertFieldSelection(OnFieldOnly.class, nullValue());
- assertMethodSelection(OnMethodOnly.class, nullValue());
- assertParameterSelection(OnParameterOnly.class, nullValue());
-
- registry.getDefaultBindings().addAll(Bindings.newDefaultBindings(store, new AnnotationRegistry()));
-
- // Verifications
- assertClassSelection(OnTypeOnly.class, instanceOf(TypeGenericVisitor.class));
- assertFieldSelection(OnFieldOnly.class, instanceOf(FieldGenericVisitor.class));
- assertMethodSelection(OnMethodOnly.class, instanceOf(MethodGenericVisitor.class));
- assertParameterSelection(OnParameterOnly.class, instanceOf(ParameterGenericVisitor.class));
-
- }
-
private void assertClassSelection(Class<? extends Annotation> type, Matcher matcher) {
Selection selection = new Selection(registry, null, reporter);
selection.type(null, classNode());
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/StereotypeParserTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/StereotypeParserTestCase.java
deleted file mode 100644
index 10fc0ef..0000000
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/stereotype/StereotypeParserTestCase.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.manipulator.metadata.annotation.stereotype;
-
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.when;
-
-import java.net.URL;
-
-import org.apache.felix.ipojo.annotations.Component;
-import org.apache.felix.ipojo.annotations.Instantiate;
-import org.apache.felix.ipojo.annotations.Stereotype;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.stereotype.replay.RootAnnotationRecorder;
-import org.apache.felix.ipojo.manipulator.util.Streams;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Type;
-
-import junit.framework.TestCase;
-
-/**
- * User: guillaume
- * Date: 30/05/13
- * Time: 23:51
- */
-public class StereotypeParserTestCase extends TestCase {
- public static final String COMPONENT_DESC = Type.getType(Component.class).getDescriptor();
- public static final String INSTANTIATE_DESC = Type.getType(Instantiate.class).getDescriptor();
- @Mock
- private AnnotationVisitor av;
-
- @Mock
- private ClassVisitor cv;
-
- @Override
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- }
-
- public void testStereotypeParsing() throws Exception {
- StereotypeParser parser = new StereotypeParser();
- parser.read(resource(IsStereotype.class));
- assertTrue(parser.isStereotype());
- }
-
- public void testStereotypeParsingWithAnnotations() throws Exception {
-
- when(cv.visitAnnotation(COMPONENT_DESC, false))
- .thenReturn(av);
- when(cv.visitAnnotation(INSTANTIATE_DESC, false))
- .thenReturn(av);
-
- StereotypeParser parser = new StereotypeParser();
- parser.read(resource(ComponentInstanceStereotype.class));
- assertTrue(parser.isStereotype());
- assertEquals(2, parser.getRecorders().size());
-
- RootAnnotationRecorder rec1 = parser.getRecorders().get(0);
- rec1.accept(cv);
- RootAnnotationRecorder rec2 = parser.getRecorders().get(1);
- rec2.accept(cv);
-
- InOrder order = inOrder(cv, av);
- order.verify(cv).visitAnnotation(COMPONENT_DESC, false);
- order.verify(av).visit("immediate", Boolean.TRUE);
- order.verify(av).visitEnd();
- order.verify(cv).visitAnnotation(INSTANTIATE_DESC, false);
- order.verify(av).visitEnd();
- }
-
- public void testNoStereotypeParsing() throws Exception {
- StereotypeParser parser = new StereotypeParser();
- parser.read(resource(NoStereotype.class));
- assertFalse(parser.isStereotype());
- }
-
- private byte[] resource(final Class<?> aClass) throws Exception {
- String name = aClass.getDeclaringClass().getSimpleName() +
- "$" + aClass.getSimpleName()
- + ".class";
- URL url = aClass.getResource(name);
- return Streams.readBytes(url.openStream());
- }
-
- @Stereotype
- public static @interface IsStereotype {}
-
- public static @interface NoStereotype {}
-
- @Component(immediate = true)
- @Instantiate
- @Stereotype
- public static @interface ComponentInstanceStereotype {}
-
-}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java
index ca3e751..f6f6ebe 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java
@@ -20,9 +20,16 @@
package org.apache.felix.ipojo.manipulator.spi;
import junit.framework.TestCase;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.HandlerBinding;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.AnnotationLiteral;
import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.GenericVisitorFactory;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ignore.NullBinding;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.stereotype.StereotypeVisitorFactory;
import java.lang.annotation.ElementType;
import java.util.Iterator;
@@ -30,6 +37,7 @@
import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.on;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.only;
+import static org.objectweb.asm.Type.getType;
/**
* Created with IntelliJ IDEA.
@@ -52,7 +60,7 @@
Iterator<Binding> i = module.iterator();
Binding one = i.next();
assertNotNull(one);
- assertEquals(Provides.class, one.getAnnotationType());
+ assertEquals(getType(Provides.class), one.getAnnotationType());
assertEquals(factory, one.getFactory());
// Only 1 Binding
@@ -72,13 +80,13 @@
Iterator<Binding> i = module.iterator();
Binding one = i.next();
assertNotNull(one);
- assertEquals(Provides.class, one.getAnnotationType());
+ assertEquals(getType(Provides.class), one.getAnnotationType());
assertEquals(factory, one.getFactory());
// Second Binding
Binding two = i.next();
assertNotNull(two);
- assertEquals(Requires.class, two.getAnnotationType());
+ assertEquals(getType(Requires.class), two.getAnnotationType());
assertEquals(factory, two.getFactory());
}
@@ -96,13 +104,13 @@
Iterator<Binding> i = module.iterator();
Binding one = i.next();
assertNotNull(one);
- assertEquals(Provides.class, one.getAnnotationType());
+ assertEquals(getType(Provides.class), one.getAnnotationType());
assertEquals(factory, one.getFactory());
// Second Binding
Binding two = i.next();
assertNotNull(two);
- assertEquals(Provides.class, two.getAnnotationType());
+ assertEquals(getType(Provides.class), two.getAnnotationType());
assertEquals(factory2, two.getFactory());
}
@@ -120,7 +128,7 @@
Iterator<Binding> i = module.iterator();
Binding one = i.next();
assertNotNull(one);
- assertEquals(Provides.class, one.getAnnotationType());
+ assertEquals(getType(Provides.class), one.getAnnotationType());
assertEquals(factory, one.getFactory());
// Only 1 Binding
@@ -135,8 +143,8 @@
bind(Provides.class)
.when(on(ElementType.FIELD))
.to(factory)
- .when(on(ElementType.PARAMETER))
- .to(factory2);
+ .when(on(ElementType.PARAMETER))
+ .to(factory2);
}
};
module.configure();
@@ -144,15 +152,111 @@
Iterator<Binding> i = module.iterator();
Binding one = i.next();
assertNotNull(one);
- assertEquals(Provides.class, one.getAnnotationType());
+ assertEquals(getType(Provides.class), one.getAnnotationType());
assertEquals(factory, one.getFactory());
// Second Binding
Binding two = i.next();
assertNotNull(two);
- assertEquals(Provides.class, two.getAnnotationType());
+ assertEquals(getType(Provides.class), two.getAnnotationType());
assertEquals(factory2, two.getFactory());
}
+ public void testHandlerBindings() throws Exception {
+ AbsBindingModule module = new AbsBindingModule() {
+ public void configure() {
+ bindHandlerBinding(Bound.class).to("com.acme", "foo");
+ }
+ };
+ module.configure();
+
+ Iterator<Binding> i = module.iterator();
+ Binding one = i.next();
+ assertNotNull(one);
+ assertEquals(getType(Bound.class), one.getAnnotationType());
+ assertTrue(one.getFactory() instanceof GenericVisitorFactory);
+ }
+
+ public void testStereotypeBindings() throws Exception {
+ AbsBindingModule module = new AbsBindingModule() {
+ public void configure() {
+ bindStereotype(Bound.class)
+ .with(new ComponentLiteral() {
+ @Override
+ public boolean publicFactory() {
+ return false;
+ }
+ });
+ }
+ };
+ module.configure();
+
+ Iterator<Binding> i = module.iterator();
+ Binding one = i.next();
+ assertNotNull(one);
+ assertEquals(getType(Bound.class), one.getAnnotationType());
+ assertTrue(one.getFactory() instanceof StereotypeVisitorFactory);
+ }
+
+
+ public void testIgnoreBindings() throws Exception {
+ AbsBindingModule module = new AbsBindingModule() {
+ public void configure() {
+ bindIgnore(Bound.class);
+ }
+ };
+ module.configure();
+
+ Iterator<Binding> i = module.iterator();
+ Binding one = i.next();
+ assertEquals(getType(Bound.class), one.getAnnotationType());
+ assertTrue(one instanceof NullBinding);
+ }
+
+ private static @interface Bound {}
+
+ private static class ComponentLiteral extends AnnotationLiteral<Component> implements Component {
+
+ public boolean public_factory() {
+ return true;
+ }
+
+ public boolean publicFactory() {
+ return true;
+ }
+
+ public String name() {
+ return "";
+ }
+
+ public boolean architecture() {
+ return false;
+ }
+
+ public boolean immediate() {
+ return false;
+ }
+
+ public boolean propagation() {
+ return false;
+ }
+
+ public String managedservice() {
+ return "";
+ }
+
+ public String factory_method() {
+ return "";
+ }
+
+ public String factoryMethod() {
+ return "";
+ }
+
+ public String version() {
+ return "";
+ }
+ }
+
}