onami-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From noctar...@apache.org
Subject svn commit: r1428001 [1/3] - in /incubator/onami/sandbox/factoryannotation: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/onami/ src/main/java/org/apache/onami/factoryannotation/ src/main/java/or...
Date Wed, 02 Jan 2013 20:28:50 GMT
Author: noctarius
Date: Wed Jan  2 20:28:48 2013
New Revision: 1428001

URL: http://svn.apache.org/viewvc?rev=1428001&view=rev
Log:
Contributed FactoryAnnotation Guice addition to Apache Onami - Currently FactoryAnnotation depends on sisu-guice 3.1.x until Guice 4 is released

Added:
    incubator/onami/sandbox/factoryannotation/   (with props)
    incubator/onami/sandbox/factoryannotation/pom.xml
    incubator/onami/sandbox/factoryannotation/src/
    incubator/onami/sandbox/factoryannotation/src/main/
    incubator/onami/sandbox/factoryannotation/src/main/java/
    incubator/onami/sandbox/factoryannotation/src/main/java/org/
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/AccessibleHelper.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBinding.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBindungTargetVisitor.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationCacheable.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationModule.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvider.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderFactory.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderInjectionAdapter.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvision.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionImpl.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionListener.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationSingleFieldMemberInjector.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/PrivilegedHelper.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/ProvisionCacheIdentityProviderFacade.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/builder/
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/builder/BindFactoryAnnotationBindingBuilder.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/builder/CombinedListenerCacheableBindingBuilder.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/builder/FactoryAnnotationAnnotationBindingBuilder.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/builder/FactoryAnnotationBaseProviderBindingBuilder.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/builder/FactoryAnnotationCacheableBindingBuilder.java
    incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/builder/FactoryAnnotationProvisionListenerBindingBuilder.java
    incubator/onami/sandbox/factoryannotation/src/test/
    incubator/onami/sandbox/factoryannotation/src/test/java/
    incubator/onami/sandbox/factoryannotation/src/test/java/org/
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/CacheableProviderTestCase.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/DeepInjectionTestCase.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderTestCase.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/InjectedValueProviderTestCase.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/InterfaceTestCase.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/ListenerMultiInjectionTestCase.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/ListenerSingleInjectionTestCase.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/MethodInjectionTestCase.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/TypeLiteralTestCase.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/annotations/
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/annotations/CacheableUser.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/annotations/Message.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/annotations/SecondLayer.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/annotations/User.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/impl/
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/impl/CacheableUserValueInjector.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/impl/InjectedUserValueInjector.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/impl/MessageEntity.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/impl/MessageValueInjector.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/impl/SecondLayerEntity.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/impl/SecondLayerIdentityProvider.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/impl/UserEntity.java
    incubator/onami/sandbox/factoryannotation/src/test/java/org/apache/onami/factoryannotation/impl/UserValueInjector.java

Propchange: incubator/onami/sandbox/factoryannotation/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed Jan  2 20:28:48 2013
@@ -0,0 +1,4 @@
+.classpath
+.project
+.settings
+target

Added: incubator/onami/sandbox/factoryannotation/pom.xml
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/pom.xml?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/pom.xml (added)
+++ incubator/onami/sandbox/factoryannotation/pom.xml Wed Jan  2 20:28:48 2013
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ | 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.onami</groupId>
+    <artifactId>org.apache.onami.parent</artifactId>
+    <version>2-incubating-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.apache.onami.factoryannotation</artifactId>
+  <version>0.1.0-incubating-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>Apache Onami-FactoryAnnotation</name>
+  <description>Apache Onami-FactoryAnnotation is a way of using assisted injection in form of factory annotations</description>
+  <url>http://onami.incubator.apache.org/factoryannotation/</url>
+  <inceptionYear>2012</inceptionYear>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.sonatype.sisu</groupId>
+      <artifactId>sisu-guice</artifactId>
+      <version>3.1.2</version>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/AccessibleHelper.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/AccessibleHelper.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/AccessibleHelper.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/AccessibleHelper.java Wed Jan  2 20:28:48 2013
@@ -0,0 +1,69 @@
+/*
+ * 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.onami.factoryannotation;
+
+import java.lang.reflect.AccessibleObject;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+class AccessibleHelper<T extends AccessibleObject>
+    implements PrivilegedAction<T>
+{
+
+    private final T object;
+
+    private final AccessibleHelperCallback<T> callback;
+
+    public AccessibleHelper( final T object, final AccessibleHelperCallback<T> callback )
+    {
+
+        this.object = object;
+        this.callback = callback;
+    }
+
+    public T run()
+    {
+        final boolean accessible = object.isAccessible();
+        if ( !accessible )
+        {
+            object.setAccessible( true );
+        }
+
+        callback.execute( object );
+
+        object.setAccessible( accessible );
+
+        return object;
+    }
+
+    public static final <T extends AccessibleObject> void executePrivileged( final T object,
+                                                                             final AccessibleHelperCallback<T> callback )
+    {
+
+        AccessController.doPrivileged( new AccessibleHelper<T>( object, callback ) );
+    }
+
+    static interface AccessibleHelperCallback<T>
+    {
+
+        void execute( T accessibleObject );
+
+    }
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBinding.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBinding.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBinding.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBinding.java Wed Jan  2 20:28:48 2013
@@ -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.onami.factoryannotation;
+
+import java.lang.annotation.Annotation;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.HasDependencies;
+
+/**
+ * A binding interface representing the actual annotation factory based binding
+ * 
+ * @param <T> The type to be injected
+ * @param <A> Annotation type where injection happens
+ */
+public interface FactoryAnnotationBinding<T, A extends Annotation>
+    extends HasDependencies
+{
+
+    /**
+     * Returns the {@link TypeLiteral} of the element to be injected.
+     */
+    TypeLiteral<T> getElementTypeLiteral();
+
+    /**
+     * Returns the bound annotation type this binding reacts on.
+     */
+    Class<A> getAnnotationType();
+
+    /**
+     * Tests the annotation for be handled by the underlying {@link FactoryAnnotationProvider}.
+     * 
+     * @param annotation An actual annotation to be tested for being accepted by the underlying
+     *            {@link FactoryAnnotationProvider} .
+     */
+    boolean acceptAnnotation( A annotation );
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBindungTargetVisitor.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBindungTargetVisitor.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBindungTargetVisitor.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationBindungTargetVisitor.java Wed Jan  2 20:28:48 2013
@@ -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.onami.factoryannotation;
+
+import java.lang.annotation.Annotation;
+
+import com.google.inject.spi.BindingTargetVisitor;
+
+/**
+ * A visitor for an annotation factory based binding extension.
+ * <p>
+ * If your {@link BindingTargetVisitor} implements this interface all bindings created by
+ * {@link FactoryAnnotationModule} will be visited through this interface.
+ * 
+ * @param <T> The type to be injected
+ * @param <V> Any return value type returned by the implementation of this interface
+ */
+public interface FactoryAnnotationBindungTargetVisitor<T, V>
+    extends BindingTargetVisitor<T, V>
+{
+
+    /**
+     * Visits the {@link FactoryAnnotationBinding} representing this annotation factory based binding
+     * 
+     * @param binding The representing annotation factory binding
+     * @return Any value returned by the visitor
+     */
+    <A extends Annotation> V visit( FactoryAnnotationBinding<T, A> binding );
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationCacheable.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationCacheable.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationCacheable.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationCacheable.java Wed Jan  2 20:28:48 2013
@@ -0,0 +1,39 @@
+/*
+ * 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.onami.factoryannotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p>
+ * This annotation can be used to mark an instance returned by the underlying {@link FactoryAnnotationProvider} to be
+ * cached instead of being newly requested on every provision.
+ * </p>
+ * <p>
+ * As an alternative you can specify an cacheable value by using the fluent language in
+ * {@link FactoryAnnotationModule#configure()}.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.ANNOTATION_TYPE } )
+public @interface FactoryAnnotationCacheable
+{
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationModule.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationModule.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationModule.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationModule.java Wed Jan  2 20:28:48 2013
@@ -0,0 +1,504 @@
+/*
+ * 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.onami.factoryannotation;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.onami.factoryannotation.PrivilegedHelper.PrivilegedHelperCallback;
+import org.apache.onami.factoryannotation.builder.BindFactoryAnnotationBindingBuilder;
+import org.apache.onami.factoryannotation.builder.CombinedListenerCacheableBindingBuilder;
+import org.apache.onami.factoryannotation.builder.FactoryAnnotationAnnotationBindingBuilder;
+import org.apache.onami.factoryannotation.builder.FactoryAnnotationBaseProviderBindingBuilder;
+
+import com.google.common.base.Preconditions;
+import com.google.inject.Binder;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Scope;
+import com.google.inject.ScopeAnnotation;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.ScopedBindingBuilder;
+import com.google.inject.internal.Annotations;
+import com.google.inject.internal.Errors;
+import com.google.inject.internal.Scoping;
+
+/**
+ * A module builder for configuring annotation factory based injections. <h3>Creating a factory annotation</h3> Factory
+ * annotations used to create an factory annotation based binding for injections. These annotations itself must be
+ * annotated by Guice' own {@literal @}{@link BindingAnnotation} annotation to be recognized as injection point and have
+ * at least one method (or annotation property);
+ * 
+ * <pre>
+ * {@literal @}BindingAnnotation
+ * {@literal @}Retention(RetentionPolicy.RUNTIME)
+ * {@literal @}Target({ ElementType.FIELD, ElementType.PARAMETER })
+ * public {@literal @}interface User {
+ * 
+ *     int byId();
+ *     
+ * }
+ * </pre>
+ * 
+ * In this example we define a {@literal @}User annotation to hold the value of the userId to be retrieved from the
+ * datastore. <h3>Implementing a FactoryAnnotationProvider</h3> An {@link FactoryAnnotationProvider} is a special
+ * provider to return the actual instance of a injection type in combination with the actual factoey annotation at the
+ * injection point. At this point we omit the UserEntity class. It can be a simple POJO, a JPA entity or whatever class
+ * you can image.
+ * 
+ * <pre>
+ * public class UserEntityProvider implements FactoryAnnotationProvider<UserEntity, User> {
+ * 
+ *     {@literal @}Override
+ *     public UserEntity buildValue(final User annotation) {
+ *         return getRealEntityById(annotation.byId());
+ *     }
+ *     
+ *     {@literal @}Override
+ *     public Class<UserEntity> getInjectionType() {
+ *         return UserEntity.class;
+ *     }
+ * 
+ *     private UserEntity getRealEntityById(int id) {
+ *         ...
+ *     }
+ *     
+ * }
+ * </pre>
+ * 
+ * The provider implementation can get an instance from nearly everywhere. It can have injection points itself, for
+ * example an EntityManager for JPA based retrieving of the entities to be injected. <h3>Configure the factory
+ * annotation based injection</h3> For configuring an factory annotation based injection {@link FactoryAnnotationModule}
+ * class is used. Like the normal {@link Module} it is configured by using the {@link Module#configure()} method. A
+ * binding is a combination of the type to be injected, the annotation type the injection should handle (compared to
+ * Guice' normal injection mechanism this is just the type, no real annotation is bound here) and at least the
+ * {@link FactoryAnnotationProvider} implementation. Additionally a {@link FactoryAnnotationProvisionListener}
+ * implementation could be bound to be notified before or after a provision by this {@link FactoryAnnotationProvider}.
+ * 
+ * <pre>
+ * Injector injector = Guice.createInjector(new IdentityModule() {
+ *     
+ *     {@literal @}Override
+ *     public void configure() {
+ *         bindType(UserEntity.class).annotatedWith(User.class)
+ *                 .toAnnotationFactory(UserEntityProvider.class);
+ *                 
+ *         bindType(UserEntity.class).annotatedWith(ListenedUser.class)
+ *                 .applyListener(getFactoryAnnotationProvisionListener())
+ *                 .toAnnotationFactory(UserEntityProvider.class);
+ *     }
+ *     
+ * });
+ * </pre>
+ */
+public abstract class FactoryAnnotationModule
+    implements Module
+{
+
+    private final Map<ScopedKey<?>, FactoryAnnotationProviderFactory<?, ?>> providerFactoryCache =
+        new HashMap<ScopedKey<?>, FactoryAnnotationProviderFactory<?, ?>>();
+
+    private Binder binder;
+
+    /**
+     * This method starts an actual binding process for a class type
+     * 
+     * @param injectionType The type of the class that should be bound
+     */
+    protected <T> FactoryAnnotationAnnotationBindingBuilder bindType( final Class<T> injectionType )
+    {
+
+        return bindIdentity( TypeLiteral.get( injectionType ) );
+    }
+
+    /**
+     * This method starts an actual binding process for a class type
+     * 
+     * @param injectionType The {@link TypeLiteral} of the class that should be bound
+     */
+    protected <T> FactoryAnnotationAnnotationBindingBuilder bindIdentity( final TypeLiteral<T> injectionType )
+    {
+
+        return new IdentityAnnotationBindingBuilderImpl<T>( injectionType, null, null );
+
+    }
+
+    /**
+     * This scopes an {@link FactoryAnnotationProvider} to an annotation annotated by {@literal @}
+     * {@link ScopeAnnotation}.
+     * 
+     * @param scopeAnnotation Annotation type to use for scope binding
+     */
+    protected <A extends Annotation> BindFactoryAnnotationBindingBuilder in( final Class<A> scopeAnnotation )
+    {
+
+        Preconditions.checkNotNull( scopeAnnotation, "scopeAnnotation" );
+
+        return new BindIdentityBindingBuilderImpl( scopeAnnotation, null );
+    }
+
+    /**
+     * This scopes an {@link FactoryAnnotationProvider} to the given {@link Scope} annotation.
+     * 
+     * @param scope {@link Scope} annotation to use for scope binding
+     */
+    protected BindFactoryAnnotationBindingBuilder in( final Scope scope )
+    {
+        Preconditions.checkNotNull( scope, "scope" );
+
+        return new BindIdentityBindingBuilderImpl( null, scope );
+    }
+
+    public void configure( final Binder binder )
+    {
+        checkState( this.binder == null, "Re-entry is not allowed." );
+
+        this.binder = checkNotNull( binder, "binder" );
+        try
+        {
+            configure();
+        }
+        finally
+        {
+            this.binder = null;
+        }
+    }
+
+    protected Binder binder()
+    {
+        return binder;
+    }
+
+    protected abstract void configure();
+
+    private final class BindIdentityBindingBuilderImpl
+        implements BindFactoryAnnotationBindingBuilder
+    {
+
+        private final Scope scope;
+
+        private final Class<? extends Annotation> scopeAnnotation;
+
+        private BindIdentityBindingBuilderImpl( final Class<? extends Annotation> scopeAnnotation, final Scope scope )
+        {
+
+            this.scopeAnnotation = scopeAnnotation;
+            this.scope = scope;
+        }
+
+        public <T> FactoryAnnotationAnnotationBindingBuilder bindIdentity( final Class<T> injectionType )
+        {
+
+            return new IdentityAnnotationBindingBuilderImpl<T>( TypeLiteral.get( injectionType ), scopeAnnotation,
+                                                                scope );
+        }
+
+        public <T> FactoryAnnotationAnnotationBindingBuilder bindIdentity( final TypeLiteral<T> injectionType )
+        {
+
+            return new IdentityAnnotationBindingBuilderImpl<T>( injectionType, scopeAnnotation, scope );
+        }
+    }
+
+    private final class IdentityAnnotationBindingBuilderImpl<T>
+        implements FactoryAnnotationAnnotationBindingBuilder
+    {
+
+        private final TypeLiteral<T> injectionType;
+
+        private final Scope scope;
+
+        private final Class<? extends Annotation> scopeAnnotation;
+
+        private IdentityAnnotationBindingBuilderImpl( final TypeLiteral<T> injectionType,
+                                                      final Class<? extends Annotation> scopeAnnotation,
+                                                      final Scope scope )
+        {
+
+            Preconditions.checkNotNull( injectionType );
+
+            this.injectionType = injectionType;
+            this.scopeAnnotation = scopeAnnotation;
+            this.scope = scope;
+        }
+
+        public <I extends Annotation> CombinedListenerCacheableBindingBuilder annotatedWith( final Class<I> annotationType )
+        {
+
+            Preconditions.checkNotNull( annotationType, "annotationType" );
+
+            Preconditions.checkArgument( Annotations.isRetainedAtRuntime( annotationType ),
+                                         "%s is not retained at runtime. Please annotate it with @Retention(RUNTIME).",
+                                         annotationType.getName() );
+
+            Preconditions.checkArgument( Annotations.isBindingAnnotation( annotationType ),
+                                         "%s is not a binding annotation. Please annotate it with @BindingAnnotation.",
+                                         annotationType.getName() );
+
+            final boolean cacheable = annotationType.isAnnotationPresent( FactoryAnnotationCacheable.class );
+
+            return new IdentityProviderBindingBuilderImpl<T>( injectionType, scopeAnnotation, scope, null,
+                                                              annotationType, cacheable );
+        }
+    }
+
+    private final class IdentityProviderBindingBuilderImpl<T>
+        implements CombinedListenerCacheableBindingBuilder
+    {
+
+        private final TypeLiteral<T> injectionType;
+
+        private final Scope scope;
+
+        private final Class<? extends Annotation> scopeAnnotation;
+
+        private final Class<? extends Annotation> annotationType;
+
+        private final FactoryAnnotationProvisionListener<?, ?> provisionListener;
+
+        private final boolean cacheable;
+
+        private IdentityProviderBindingBuilderImpl( final TypeLiteral<T> injectionType,
+                                                    final Class<? extends Annotation> scopeAnnotation,
+                                                    final Scope scope,
+                                                    final FactoryAnnotationProvisionListener<?, ?> provisionListener,
+                                                    final Class<? extends Annotation> annotationType,
+                                                    final boolean cacheable )
+        {
+
+            this.injectionType = injectionType;
+            this.scopeAnnotation = scopeAnnotation;
+            this.scope = scope;
+            this.provisionListener = provisionListener;
+            this.annotationType = annotationType;
+            this.cacheable = cacheable;
+        }
+
+        @SuppressWarnings( "unchecked" )
+        public <I, A extends Annotation> void toAnnotationFactory( final FactoryAnnotationProvider<I, A> factoryAnnotationProvider )
+        {
+
+            Preconditions.checkNotNull( factoryAnnotationProvider, "factoryAnnotationProvider" );
+
+            final Class<I> keyType = factoryAnnotationProvider.getInjectionType();
+
+            if ( !keyType.equals( injectionType.getRawType() ) )
+            {
+                new Errors().cannotInjectTypeLiteralOf( keyType ).throwConfigurationExceptionIfErrorsExist();
+            }
+
+            final ScopedKey<T> cacheKey =
+                buildScopedKey( factoryAnnotationProvider.getClass(), annotationType, scopeAnnotation, scope );
+
+            final FactoryAnnotationProviderFactory<I, A> provider;
+            if ( providerFactoryCache.containsKey( cacheKey ) )
+            {
+                provider = (FactoryAnnotationProviderFactory<I, A>) providerFactoryCache.get( cacheKey );
+
+            }
+            else
+            {
+                provider =
+                    new FactoryAnnotationProviderFactory<I, A>(
+                                                                binder(),
+                                                                (Class<A>) annotationType,
+                                                                factoryAnnotationProvider,
+                                                                (FactoryAnnotationProvisionListener<I, A>) provisionListener,
+                                                                cacheable );
+
+                providerFactoryCache.put( cacheKey, provider );
+
+                final ScopedBindingBuilder scopeBuilder =
+                    binder().bind( keyType ).annotatedWith( annotationType ).toProvider( provider );
+
+                if ( scope != null )
+                {
+                    scopeBuilder.in( scope );
+
+                }
+                else if ( scopeAnnotation != null )
+                {
+                    scopeBuilder.in( scopeAnnotation );
+                }
+            }
+        }
+
+        public <I, A extends Annotation> void toIdentityProvider( final Class<FactoryAnnotationProvider<I, A>> factoryAnnotationProviderType )
+        {
+
+            Preconditions.checkNotNull( factoryAnnotationProviderType, "factoryAnnotationProviderType" );
+
+            final FactoryAnnotationProvider<I, A> identityProvider =
+                PrivilegedHelper.executePrivileged( factoryAnnotationProviderType,
+                                                    new PrivilegedHelperCallback<FactoryAnnotationProvider<I, A>>()
+                                                    {
+
+                                                        public FactoryAnnotationProvider<I, A> execute( final Class<FactoryAnnotationProvider<I, A>> clazz )
+                                                        {
+
+                                                            try
+                                                            {
+                                                                return clazz.newInstance();
+
+                                                            }
+                                                            catch ( final InstantiationException e )
+                                                            {
+                                                                throw new RuntimeException( e );
+
+                                                            }
+                                                            catch ( final IllegalAccessException e )
+                                                            {
+                                                                throw new RuntimeException( e );
+                                                            }
+                                                        }
+                                                    } );
+
+            toAnnotationFactory( identityProvider );
+        }
+
+        @SuppressWarnings( "unchecked" )
+        public <I, A extends Annotation> FactoryAnnotationBaseProviderBindingBuilder applyListener( final FactoryAnnotationProvisionListener<I, A> provisionListener )
+        {
+
+            Preconditions.checkNotNull( provisionListener, "provisionListener" );
+
+            return new IdentityProviderBindingBuilderImpl<I>( (TypeLiteral<I>) injectionType, scopeAnnotation, scope,
+                                                              provisionListener, annotationType, cacheable );
+        }
+
+        @SuppressWarnings( "unchecked" )
+        public <I, A extends Annotation> CombinedListenerCacheableBindingBuilder cacheable()
+        {
+            return new IdentityProviderBindingBuilderImpl<I>( (TypeLiteral<I>) injectionType, scopeAnnotation, scope,
+                                                              provisionListener, annotationType, true );
+        }
+
+        @SuppressWarnings( "unchecked" )
+        public <I, A extends Annotation> CombinedListenerCacheableBindingBuilder nonCacheable()
+        {
+            return new IdentityProviderBindingBuilderImpl<I>( (TypeLiteral<I>) injectionType, scopeAnnotation, scope,
+                                                              provisionListener, annotationType, false );
+        }
+
+        @SuppressWarnings( "unchecked" )
+        private ScopedKey<T> buildScopedKey( final Class<?> type, final Class<? extends Annotation> annotationType,
+                                             final Class<? extends Annotation> scopeAnnotation, final Scope scope )
+        {
+
+            final Scoping scoping;
+            if ( scopeAnnotation != null )
+            {
+                scoping = Scoping.forAnnotation( scopeAnnotation );
+
+            }
+            else if ( scope != null )
+            {
+                scoping = Scoping.forInstance( scope );
+
+            }
+            else
+            {
+                scoping = null;
+            }
+
+            return new ScopedKey<T>( (Key<T>) Key.get( type, annotationType ), scoping );
+        }
+    }
+
+    private class ScopedKey<T>
+    {
+        private final Key<T> key;
+
+        private final Scoping scoping;
+
+        private ScopedKey( final Key<T> key, final Scoping scoping )
+        {
+            this.key = key;
+            this.scoping = scoping;
+        }
+
+        @Override
+        public int hashCode()
+        {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + getOuterType().hashCode();
+            result = prime * result + ( ( key == null ) ? 0 : key.hashCode() );
+            result = prime * result + ( ( scoping == null ) ? 0 : scoping.hashCode() );
+            return result;
+        }
+
+        @Override
+        public boolean equals( final Object obj )
+        {
+            if ( this == obj )
+            {
+                return true;
+            }
+            if ( obj == null )
+            {
+                return false;
+            }
+            if ( getClass() != obj.getClass() )
+            {
+                return false;
+            }
+            final ScopedKey<?> other = (ScopedKey<?>) obj;
+            if ( !getOuterType().equals( other.getOuterType() ) )
+            {
+                return false;
+            }
+            if ( key == null )
+            {
+                if ( other.key != null )
+                {
+                    return false;
+                }
+            }
+            else if ( !key.equals( other.key ) )
+            {
+                return false;
+            }
+            if ( scoping == null )
+            {
+                if ( other.scoping != null )
+                {
+                    return false;
+                }
+            }
+            else if ( !scoping.equals( other.scoping ) )
+            {
+                return false;
+            }
+            return true;
+        }
+
+        private FactoryAnnotationModule getOuterType()
+        {
+            return FactoryAnnotationModule.this;
+        }
+
+    }
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvider.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvider.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvider.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvider.java Wed Jan  2 20:28:48 2013
@@ -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.onami.factoryannotation;
+
+import java.lang.annotation.Annotation;
+
+import com.google.inject.Injector;
+
+/**
+ * The interface to describe a FactoryAnnotationProvider bound by {@link FactoryAnnotationModule} to the Guice
+ * {@link Injector}. <h3>Implementing a FactoryAnnotationProvider</h3> An {@link FactoryAnnotationProvider} is a special
+ * provider to return the actual instance of a injection type in combination with the actual factory annotation at the
+ * injection point. At this point we omit the UserEntity class. It can be a simple POJO, a JPA entity or whatever class
+ * you can image.
+ * 
+ * <pre>
+ * public class UserEntityProvider implements FactoryAnnotationProvider<UserEntity, User> {
+ * 
+ *     {@literal @}Override
+ *     public UserEntity buildValue(final User annotation) {
+ *         return getRealEntityById(annotation.byId());
+ *     }
+ *     
+ *     {@literal @}Override
+ *     public Class<UserEntity> getInjectionType() {
+ *         return UserEntity.class;
+ *     }
+ * 
+ *     private UserEntity getRealEntityById(int id) {
+ *         ...
+ *     }
+ *     
+ * }
+ * </pre>
+ * 
+ * @param <T> The type to be injected
+ * @param <A> Annotation type where injection happens
+ */
+public interface FactoryAnnotationProvider<T, A extends Annotation>
+{
+
+    /**
+     * Returns the type of injection points that should be captured for provision.
+     */
+    Class<T> getInjectionType();
+
+    /**
+     * <p>
+     * The implementation of this method is responsible for building / requesting the instance that is referenced by the
+     * actual injection points annotation to the annotation type bound at configuration time.
+     * </p>
+     * <p>
+     * For more information see {@link FactoryAnnotationModule}.
+     * </p>
+     * 
+     * @param annotation The actual annotation of the bound annotation type at the provision injection point.
+     * @return The actual instance for a given annotation based value.
+     */
+    T buildValue( A annotation );
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderFactory.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderFactory.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderFactory.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderFactory.java Wed Jan  2 20:28:48 2013
@@ -0,0 +1,257 @@
+/*
+ * 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.onami.factoryannotation;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.ProvisionException;
+import com.google.inject.TypeLiteral;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.BindingTargetVisitor;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.DependencyAndSource;
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
+import com.google.inject.spi.ProvisionListener;
+import com.google.inject.spi.TypeEncounter;
+import com.google.inject.spi.TypeListener;
+
+final class FactoryAnnotationProviderFactory<T, A extends Annotation>
+    extends DefaultBindingTargetVisitor<T, Object>
+    implements TypeListener, ProviderWithExtensionVisitor<T>, HasDependencies, ProvisionListener,
+    FactoryAnnotationBinding<T, A>
+{
+
+    private final Class<A> annotationType;
+
+    private final FactoryAnnotationProvider<T, A> factoryAnnotationProvider;
+
+    private final Key<FactoryAnnotationProvider<T, A>> targetKey;
+
+    private final TypeLiteral<T> elementTypeLiteral;
+
+    private final FactoryAnnotationProvisionListener<T, A> provisionListener;
+
+    private final ThreadLocal<A> provision = new ThreadLocal<A>();
+
+    @SuppressWarnings( "unchecked" )
+    FactoryAnnotationProviderFactory( final Binder binder, final Class<A> annotationType,
+                                      final FactoryAnnotationProvider<T, A> factoryAnnotationProvider,
+                                      final FactoryAnnotationProvisionListener<T, A> listener, final boolean cacheable )
+    {
+
+        this.annotationType = annotationType;
+
+        this.provisionListener = listener;
+
+        this.targetKey = (Key<FactoryAnnotationProvider<T, A>>) Key.get( factoryAnnotationProvider.getClass() );
+
+        this.elementTypeLiteral = TypeLiteral.get( factoryAnnotationProvider.getInjectionType() );
+
+        final FactoryAnnotationProvider<T, A> adapter =
+            new FactoryAnnotationProviderInjectionAdapter<T, A>( factoryAnnotationProvider );
+
+        // Request injection of the FactoryAnnotationProvider and the adapter before we
+        // want to use it to meet possible requirements of the inner
+        // implementation
+        binder.requestInjection( adapter );
+        binder.requestInjection( factoryAnnotationProvider );
+
+        // If values can be cached initialize the caching map
+        if ( cacheable )
+        {
+            this.factoryAnnotationProvider = new ProvisionCacheIdentityProviderFacade<T, A>( adapter, elementTypeLiteral );
+
+            // Now we need to request injection for cache provider as well
+            binder.requestInjection( this.factoryAnnotationProvider );
+
+        }
+        else
+        {
+            this.factoryAnnotationProvider = adapter;
+        }
+
+        binder.bindListener( Matchers.any(), this );
+        binder.bindListener( Matchers.any(), (ProvisionListener) this );
+    }
+
+    public T get()
+    {
+        final A annotation = provision.get();
+        if ( annotation == null )
+        {
+            throw new ProvisionException( "No legal provision" );
+        }
+
+        // Delete value from ThreadLocal store
+        provision.set( null );
+
+        // Return the provisioned (real) value
+        return factoryAnnotationProvider.buildValue( annotation );
+    }
+
+    public <I> void hear( final TypeLiteral<I> type, final TypeEncounter<I> encounter )
+    {
+
+        // Search for fields that needs to be injected
+        for ( final Field field : type.getRawType().getDeclaredFields() )
+        {
+            if ( field.isAnnotationPresent( annotationType ) )
+            {
+                final A annotation = annotationType.cast( field.getAnnotation( annotationType ) );
+
+                final Set<InjectionPoint> injectionPoints =
+                    InjectionPoint.forInstanceMethodsAndFields( type.getRawType() );
+
+                FactoryAnnotationProvision<T, A> identityProvision = null;
+                if ( injectionPoints.size() > 0 )
+                {
+                    for ( final InjectionPoint ip : injectionPoints )
+                    {
+                        if ( ip.getMember().equals( field ) )
+                        {
+                            identityProvision = FactoryAnnotationProvisionImpl.wrapInjectionPoint( ip, annotation );
+                        }
+                    }
+
+                }
+
+                if ( identityProvision == null )
+                {
+                    identityProvision =
+                        new FactoryAnnotationProvisionImpl<T, A>( field, annotation, field.getAnnotations(),
+                                                                  elementTypeLiteral );
+                }
+
+                // Register a MembersInjector per field which actually will do
+                // the injection for Guice
+                encounter.register( FactoryAnnotationSingleFieldMemberInjector.buildMemberInjector( factoryAnnotationProvider,
+                                                                                                    field,
+                                                                                                    provisionListener,
+                                                                                                    annotation,
+                                                                                                    identityProvision ) );
+
+            }
+        }
+    }
+
+    public <I> void onProvision( final ProvisionInvocation<I> provision )
+    {
+        final List<DependencyAndSource> dependencies = provision.getDependencyChain();
+
+        // OK here we are at constructor or method injection so let's get the
+        // real annotation at the type
+        for ( final DependencyAndSource dependency : dependencies )
+        {
+            if ( dependency.getDependency() == null )
+            {
+                continue;
+            }
+
+            final Annotation annotation = dependency.getDependency().getKey().getAnnotation();
+
+            if ( annotation != null )
+            {
+                if ( annotation.annotationType().equals( annotationType ) )
+                {
+                    // We found the real annotation, let's save it for the
+                    // actual provision call!
+                    final A specificAnnotation = annotationType.cast( annotation );
+                    this.provision.set( specificAnnotation );
+
+                    final InjectionPoint injectionPoint = dependency.getDependency().getInjectionPoint();
+
+                    if ( injectionPoint == null )
+                    {
+                        checkNotNull( injectionPoint );
+                    }
+
+                    final FactoryAnnotationProvision<T, A> identityProvision =
+                        FactoryAnnotationProvisionImpl.wrapInjectionPoint( injectionPoint, specificAnnotation );
+
+                    // Notify listener that an provision will occur
+                    if ( provisionListener != null )
+                    {
+                        provisionListener.beforeInjection( identityProvision, specificAnnotation );
+                    }
+
+                    // Execute the provision;
+                    T value = factoryAnnotationProvider.getInjectionType().cast( provision.provision() );
+
+                    // Notify listener about the provisioned value
+                    if ( provisionListener != null )
+                    {
+                        provisionListener.afterInjection( identityProvision, specificAnnotation, value );
+                    }
+
+                    // Explicitly return at this point
+                    return;
+                }
+            }
+        }
+    }
+
+    public Set<Dependency<?>> getDependencies()
+    {
+        return ImmutableSet.<Dependency<?>> of( Dependency.get( targetKey ) );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public <B, V> V acceptExtensionVisitor( final BindingTargetVisitor<B, V> visitor,
+                                            final ProviderInstanceBinding<? extends B> binding )
+    {
+
+        if ( visitor instanceof FactoryAnnotationBindungTargetVisitor )
+        {
+            return ( (FactoryAnnotationBindungTargetVisitor<T, V>) visitor ).visit( this );
+
+        }
+        else
+        {
+            return visitor.visit( binding );
+        }
+    }
+
+    public TypeLiteral<T> getElementTypeLiteral()
+    {
+        return elementTypeLiteral;
+    }
+
+    public Class<A> getAnnotationType()
+    {
+        return annotationType;
+    }
+
+    public boolean acceptAnnotation( A annotation )
+    {
+        return getAnnotationType().equals( annotation.annotationType() );
+    }
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderInjectionAdapter.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderInjectionAdapter.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderInjectionAdapter.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProviderInjectionAdapter.java Wed Jan  2 20:28:48 2013
@@ -0,0 +1,53 @@
+/*
+ * 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.onami.factoryannotation;
+
+import java.lang.annotation.Annotation;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+class FactoryAnnotationProviderInjectionAdapter<T, A extends Annotation>
+    implements FactoryAnnotationProvider<T, A>
+{
+
+    private final FactoryAnnotationProvider<T, A> factoryAnnotationProvider;
+
+    @Inject
+    private Injector injector;
+
+    FactoryAnnotationProviderInjectionAdapter( final FactoryAnnotationProvider<T, A> factoryAnnotationProvider )
+    {
+
+        this.factoryAnnotationProvider = factoryAnnotationProvider;
+    }
+
+    public Class<T> getInjectionType()
+    {
+        return factoryAnnotationProvider.getInjectionType();
+    }
+
+    public T buildValue( A annotation )
+    {
+        final T value = factoryAnnotationProvider.buildValue( annotation );
+        injector.injectMembers( value );
+        return value;
+    }
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvision.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvision.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvision.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvision.java Wed Jan  2 20:28:48 2013
@@ -0,0 +1,119 @@
+/*
+ * 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.onami.factoryannotation;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+import com.google.inject.TypeLiteral;
+
+/**
+ * This interface represents the injection point of the actual provision. In addiction to the
+ * {@link FactoryAnnotationProvisionType} returned by {@link #getProvisionType()} the methods {@link #getConstructor()},
+ * {@link #getMethod()} or {@link #getField()} methods return null or the actual {@link Member} that corresponds to the
+ * injection point.
+ * 
+ * @param <T> The type to be injected
+ * @param <A> Annotation type where injection happens
+ */
+public interface FactoryAnnotationProvision<T, A extends Annotation>
+{
+
+    /**
+     * The type of provision to be executed
+     */
+    public static enum FactoryAnnotationProvisionType
+    {
+        /**
+         * A method parameter provision
+         */
+        METHOD,
+
+        /**
+         * A constructor parameter provision
+         */
+        CONSTRUCTOR,
+
+        /**
+         * A field (instance member) provision
+         */
+        FIELD,
+
+        /**
+         * A static field (class member) provision
+         */
+        STATIC
+    }
+
+    /**
+     * Returns the type of provision that happens at this injection point
+     */
+    FactoryAnnotationProvisionType getProvisionType();
+
+    /**
+     * If the provision type is {@link FactoryAnnotationProvisionType#CONSTRUCTOR} this returns the constructor of the
+     * injection point otherwise it returns null.
+     */
+    Constructor<T> getConstructor();
+
+    /**
+     * If the provision type is {@link FactoryAnnotationProvisionType#METHOD} this returns the method of the injection
+     * point otherwise it returns null.
+     */
+    Method getMethod();
+
+    /**
+     * If the provision type is {@link FactoryAnnotationProvisionType#CONSTRUCTOR} or
+     * {@link FactoryAnnotationProvisionType#METHOD} this returns the parameter position of the parameter to be
+     * provisioned otherwise if the provision type is a field it returns -1.
+     */
+    int getParameterPosition();
+
+    /**
+     * If the provision type is {@link FactoryAnnotationProvisionType#FIELD} or
+     * {@link FactoryAnnotationProvisionType#STATIC} this returns the field of the injection point otherwise it returns
+     * null.
+     */
+    Field getField();
+
+    /**
+     * Returns the target object to be provisioned.
+     */
+    T getTarget();
+
+    /**
+     * Returns the actual annotation of the bound annotation type.
+     */
+    A getProvisionAnnotation();
+
+    /**
+     * Returns an array of all available annotations at the actual provision position (field, method- / constructor
+     * parameter).
+     */
+    Annotation[] getAnnotations();
+
+    /**
+     * Returns the {@link TypeLiteral} of the provisioned type.
+     */
+    TypeLiteral<T> getElementTypeLiteral();
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionImpl.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionImpl.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionImpl.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionImpl.java Wed Jan  2 20:28:48 2013
@@ -0,0 +1,303 @@
+/*
+ * 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.onami.factoryannotation;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import com.google.inject.ProvisionException;
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.InjectionPoint;
+
+class FactoryAnnotationProvisionImpl<T, A extends Annotation>
+    implements FactoryAnnotationProvision<T, A>
+{
+
+    private final FactoryAnnotationProvisionType provisionType;
+
+    private final Constructor<T> constructor;
+
+    private final Method method;
+
+    private final Field field;
+
+    private final A provisionAnnotation;
+
+    private final Annotation[] annotations;
+
+    private final T target;
+
+    private final int parameterPosition;
+
+    public FactoryAnnotationProvisionImpl( final Constructor<T> constructor, int parameterPosition,
+                                           final A provisionAnnotation, final Annotation[] annotations,
+                                           final TypeLiteral<T> typeLiteral )
+    {
+
+        this( FactoryAnnotationProvisionType.CONSTRUCTOR, constructor, null, parameterPosition, null,
+              provisionAnnotation, annotations, typeLiteral, null );
+    }
+
+    public FactoryAnnotationProvisionImpl( final Method method, int parameterPosition, final A provisionAnnotation,
+                                           final Annotation[] annotations, final TypeLiteral<T> typeLiteral )
+    {
+
+        this( FactoryAnnotationProvisionType.METHOD, null, method, parameterPosition, null, provisionAnnotation,
+              annotations, typeLiteral, null );
+    }
+
+    public FactoryAnnotationProvisionImpl( final Field field, final A provisionAnnotation,
+                                           final Annotation[] annotations, final TypeLiteral<T> typeLiteral )
+    {
+
+        this( FactoryAnnotationProvisionType.FIELD, null, null, -1, field, provisionAnnotation, annotations,
+              typeLiteral, null );
+    }
+
+    FactoryAnnotationProvisionImpl( final FactoryAnnotationProvisionType provisionType,
+                                    final Constructor<T> constructor, final Method method, int parameterPosition,
+                                    final Field field, final A provisionAnnotation, final Annotation[] annotations,
+                                    final TypeLiteral<T> typeLiteral, final T target )
+    {
+
+        this.provisionType = provisionType;
+        this.constructor = constructor;
+        this.method = method;
+        this.field = field;
+        this.provisionAnnotation = provisionAnnotation;
+        this.target = target;
+        this.parameterPosition = parameterPosition;
+
+        this.annotations = new Annotation[annotations.length];
+        System.arraycopy( annotations, 0, this.annotations, 0, annotations.length );
+    }
+
+    public FactoryAnnotationProvisionType getProvisionType()
+    {
+        return provisionType;
+    }
+
+    public Constructor<T> getConstructor()
+    {
+        return constructor;
+    }
+
+    public Method getMethod()
+    {
+        return method;
+    }
+
+    public Field getField()
+    {
+        return field;
+    }
+
+    public T getTarget()
+    {
+        return target;
+    }
+
+    public A getProvisionAnnotation()
+    {
+        return provisionAnnotation;
+    }
+
+    public Annotation[] getAnnotations()
+    {
+        final Annotation[] temp = new Annotation[annotations.length];
+        System.arraycopy( annotations, 0, temp, 0, annotations.length );
+        return annotations;
+    }
+
+    public int getParameterPosition()
+    {
+        return parameterPosition;
+    }
+
+    public TypeLiteral<T> getElementTypeLiteral()
+    {
+        return null;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + Arrays.hashCode( annotations );
+        result = prime * result + ( ( constructor == null ) ? 0 : constructor.hashCode() );
+        result = prime * result + ( ( field == null ) ? 0 : field.hashCode() );
+        result = prime * result + ( ( method == null ) ? 0 : method.hashCode() );
+        result = prime * result + parameterPosition;
+        result = prime * result + ( ( provisionAnnotation == null ) ? 0 : provisionAnnotation.hashCode() );
+        result = prime * result + ( ( provisionType == null ) ? 0 : provisionType.hashCode() );
+        result = prime * result + ( ( target == null ) ? 0 : target.hashCode() );
+        return result;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+            return true;
+        if ( obj == null )
+            return false;
+        if ( getClass() != obj.getClass() )
+            return false;
+        FactoryAnnotationProvisionImpl<?, ?> other = (FactoryAnnotationProvisionImpl<?, ?>) obj;
+        if ( !Arrays.equals( annotations, other.annotations ) )
+            return false;
+        if ( constructor == null )
+        {
+            if ( other.constructor != null )
+                return false;
+        }
+        else if ( !constructor.equals( other.constructor ) )
+            return false;
+        if ( field == null )
+        {
+            if ( other.field != null )
+                return false;
+        }
+        else if ( !field.equals( other.field ) )
+            return false;
+        if ( method == null )
+        {
+            if ( other.method != null )
+                return false;
+        }
+        else if ( !method.equals( other.method ) )
+            return false;
+        if ( parameterPosition != other.parameterPosition )
+            return false;
+        if ( provisionAnnotation == null )
+        {
+            if ( other.provisionAnnotation != null )
+                return false;
+        }
+        else if ( !provisionAnnotation.equals( other.provisionAnnotation ) )
+            return false;
+        if ( provisionType != other.provisionType )
+            return false;
+        if ( target == null )
+        {
+            if ( other.target != null )
+                return false;
+        }
+        else if ( !target.equals( other.target ) )
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "IdentityProvisionImpl [provisionType=" + provisionType + ", constructor=" + constructor + ", method="
+            + method + ", field=" + field + ", provisionAnnotation=" + provisionAnnotation + ", annotations="
+            + Arrays.toString( annotations ) + ", target=" + target + ", parameterPosition=" + parameterPosition + "]";
+    }
+
+    @SuppressWarnings( "unchecked" )
+    static <T, A extends Annotation> FactoryAnnotationProvision<T, A> wrapInjectionPoint( final InjectionPoint injectionPoint,
+                                                                                          final A annotation )
+    {
+
+        if ( injectionPoint.getMember() instanceof Field )
+        {
+            final Field field = (Field) injectionPoint.getMember();
+
+            return new FactoryAnnotationProvisionImpl<T, A>( field, annotation, field.getAnnotations(),
+                                                             (TypeLiteral<T>) buildTypeLiteral( field.getType() ) );
+
+        }
+        else if ( injectionPoint.getMember() instanceof Method )
+        {
+            final Method method = (Method) injectionPoint.getMember();
+            final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+
+            for ( int i = 0; i < method.getParameterTypes().length; i++ )
+            {
+                final Annotation[] annotations = parameterAnnotations[i];
+
+                for ( int o = 0; o < annotations.length; o++ )
+                {
+                    if ( annotation.equals( annotations[o] ) )
+                    {
+                        return new FactoryAnnotationProvisionImpl<T, A>(
+                                                                         method,
+                                                                         i,
+                                                                         annotation,
+                                                                         annotations,
+                                                                         (TypeLiteral<T>) buildTypeLiteral( method.getParameterTypes()[i] ) );
+                    }
+                }
+            }
+
+        }
+        else if ( injectionPoint.getMember() instanceof Constructor )
+        {
+            final Constructor<T> constructor = (Constructor<T>) injectionPoint.getMember();
+
+            final Annotation[][] parameterAnnotations = constructor.getParameterAnnotations();
+
+            for ( int i = 0; i < constructor.getParameterTypes().length; i++ )
+            {
+                final Annotation[] annotations = parameterAnnotations[i];
+
+                for ( int o = 0; o < annotations.length; o++ )
+                {
+                    if ( annotation.equals( annotations[o] ) )
+                    {
+                        return new FactoryAnnotationProvisionImpl<T, A>(
+                                                                         constructor,
+                                                                         i,
+                                                                         annotation,
+                                                                         annotations,
+                                                                         (TypeLiteral<T>) buildTypeLiteral( constructor.getParameterTypes()[i] ) );
+                    }
+                }
+            }
+        }
+
+        throw new ProvisionException( "InjectionPoint could not be transformed to FactoryAnnotationProvision" );
+    }
+
+    static <T, A extends Annotation> FactoryAnnotationProvision<T, A> modify( final FactoryAnnotationProvision<T, A> identityProvision,
+                                                                              final T target )
+    {
+
+        return new FactoryAnnotationProvisionImpl<T, A>( identityProvision.getProvisionType(),
+                                                         identityProvision.getConstructor(),
+                                                         identityProvision.getMethod(),
+                                                         identityProvision.getParameterPosition(),
+                                                         identityProvision.getField(),
+                                                         identityProvision.getProvisionAnnotation(),
+                                                         identityProvision.getAnnotations(),
+                                                         identityProvision.getElementTypeLiteral(), target );
+    }
+
+    private static <T> TypeLiteral<T> buildTypeLiteral( final Class<T> clazz )
+    {
+        return TypeLiteral.get( clazz );
+    }
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionListener.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionListener.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionListener.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationProvisionListener.java Wed Jan  2 20:28:48 2013
@@ -0,0 +1,55 @@
+/*
+ * 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.onami.factoryannotation;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * This interface needs to be implemented by all listeners that are interested in events of identity provision. Avaiable
+ * events are {@link #beforeInjection(FactoryAnnotationProvision, Annotation)} and
+ * {@link #afterInjection(FactoryAnnotationProvision, Annotation, Object)}.
+ * 
+ * @param <T> The type to be injected
+ * @param <A> Annotation type where injection happens
+ * @since 4.0
+ * @author noctarius
+ */
+public interface FactoryAnnotationProvisionListener<T, A extends Annotation>
+{
+
+    /**
+     * This event is called just before the provision will take place.
+     * 
+     * @param factoryAnnotationProvision {@link FactoryAnnotationProvision} implementation holding information about the
+     *            provision.
+     * @param provisionAnnotation The actual annotation of the bound annotation type
+     */
+    void beforeInjection( FactoryAnnotationProvision<T, A> factoryAnnotationProvision, A provisionAnnotation );
+
+    /**
+     * This event is called directly after the provision has taken place.
+     * 
+     * @param factoryAnnotationProvision {@link FactoryAnnotationProvision} implementation holding information about the
+     *            provision.
+     * @param provisionAnnotation The actual annotation of the bound annotation type
+     * @param value The value that was injected during the provision
+     */
+    void afterInjection( FactoryAnnotationProvision<T, A> factoryAnnotationProvision, A provisionAnnotation, T value );
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationSingleFieldMemberInjector.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationSingleFieldMemberInjector.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationSingleFieldMemberInjector.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/FactoryAnnotationSingleFieldMemberInjector.java Wed Jan  2 20:28:48 2013
@@ -0,0 +1,113 @@
+/*
+ * 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.onami.factoryannotation;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+import org.apache.onami.factoryannotation.AccessibleHelper.AccessibleHelperCallback;
+
+import com.google.inject.MembersInjector;
+import com.google.inject.ProvisionException;
+
+class FactoryAnnotationSingleFieldMemberInjector<T, A extends Annotation>
+    implements MembersInjector<T>
+{
+
+    private final FactoryAnnotationProvider<T, A> factoryAnnotationProvider;
+
+    private final Field field;
+
+    private final A annotation;
+
+    private final FactoryAnnotationProvision<T, A> factoryAnnotationProvision;
+
+    private final FactoryAnnotationProvisionListener<T, A> provisionListener;
+
+    FactoryAnnotationSingleFieldMemberInjector( final FactoryAnnotationProvider<T, A> factoryAnnotationProvider, final Field field,
+                                       final FactoryAnnotationProvisionListener<T, A> provisionListener, final A annotation,
+                                       final FactoryAnnotationProvision<T, A> factoryAnnotationProvision )
+    {
+
+        this.factoryAnnotationProvider = factoryAnnotationProvider;
+        this.field = field;
+        this.annotation = annotation;
+        this.factoryAnnotationProvision = factoryAnnotationProvision;
+        this.provisionListener = provisionListener;
+    }
+
+    public void injectMembers( final T instance )
+    {
+        AccessibleHelper.executePrivileged( field, new AccessibleHelperCallback<Field>()
+        {
+
+            public void execute( final Field accessibleObject )
+            {
+                try
+                {
+                    // If annotated with both @Inject and a binding
+                    // annotation it is possible that there would be two
+                    // injection request, so just prevent injecting a
+                    // value a second time
+                    if ( accessibleObject.get( instance ) == null )
+                    {
+                        final FactoryAnnotationProvision<T, A> ip = FactoryAnnotationProvisionImpl.modify( factoryAnnotationProvision, instance );
+
+                        final T value = factoryAnnotationProvider.buildValue( annotation );
+
+                        // Notify listener before we inject the value
+                        if ( provisionListener != null )
+                        {
+                            provisionListener.beforeInjection( ip, annotation );
+                        }
+
+                        accessibleObject.set( instance, value );
+
+                        // Notify listener after injection is done
+                        if ( provisionListener != null )
+                        {
+                            provisionListener.afterInjection( ip, annotation, value );
+                        }
+                    }
+
+                }
+                catch ( final IllegalAccessException e )
+                {
+                    throw new ProvisionException( "Provision failed", e );
+                }
+            }
+
+        } );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    static final <A extends Annotation, I, T> MembersInjector<I> buildMemberInjector( final FactoryAnnotationProvider<T, A> factoryAnnotationProvider,
+                                                                                      final Field field,
+                                                                                      final FactoryAnnotationProvisionListener<T, A> provisionListener,
+                                                                                      final A annotation,
+                                                                                      final FactoryAnnotationProvision<T, A> factoryAnnotationProvision )
+    {
+
+        return (MembersInjector<I>) new FactoryAnnotationSingleFieldMemberInjector<T, A>( factoryAnnotationProvider, field,
+                                                                                 provisionListener, annotation,
+                                                                                 factoryAnnotationProvision );
+
+    }
+
+}

Added: incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/PrivilegedHelper.java
URL: http://svn.apache.org/viewvc/incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/PrivilegedHelper.java?rev=1428001&view=auto
==============================================================================
--- incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/PrivilegedHelper.java (added)
+++ incubator/onami/sandbox/factoryannotation/src/main/java/org/apache/onami/factoryannotation/PrivilegedHelper.java Wed Jan  2 20:28:48 2013
@@ -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.onami.factoryannotation;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+class PrivilegedHelper<T>
+    implements PrivilegedAction<T>
+{
+
+    private final Class<T> clazz;
+
+    private final PrivilegedHelperCallback<T> callback;
+
+    public PrivilegedHelper( final Class<T> clazz, final PrivilegedHelperCallback<T> callback )
+    {
+
+        this.clazz = clazz;
+        this.callback = callback;
+    }
+
+    public T run()
+    {
+        return callback.execute( clazz );
+    }
+
+    public static final <T> T executePrivileged( final Class<T> clazz, final PrivilegedHelperCallback<T> callback )
+    {
+
+        return AccessController.doPrivileged( new PrivilegedHelper<T>( clazz, callback ) );
+    }
+
+    static interface PrivilegedHelperCallback<T>
+    {
+
+        T execute( Class<T> clazz );
+
+    }
+
+}



Mime
View raw message