Author: rgielen
Date: Tue Feb 28 00:28:57 2012
New Revision: 1294413

URL: http://svn.apache.org/viewvc?rev=1294413&view=rev
Log:
Simple code reformatting, no actual change.

Modified:
    
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java

Modified: 
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
URL: 
http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java?rev=1294413&r1=1294412&r2=1294413&view=diff
==============================================================================
--- 
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
 (original)
+++ 
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
 Tue Feb 28 00:28:57 2012
@@ -28,594 +28,602 @@ import java.security.AccessControlExcept
 /**
  * Default {@link Container} implementation.
  *
- * @see ContainerBuilder
  * @author crazy...@google.com (Bob Lee)
+ * @see ContainerBuilder
  */
 class ContainerImpl implements Container {
 
-  final Map<Key<?>, InternalFactory<?>> factories;
-  final Map<Class<?>,Set<String>> factoryNamesByType;
+       final Map<Key<?>, InternalFactory<?>> factories;
+       final Map<Class<?>, Set<String>> factoryNamesByType;
 
-  ContainerImpl(Map<Key<?>, InternalFactory<?>> factories) {
-    this.factories = factories;
-    Map<Class<?>,Set<String>> map = new HashMap<Class<?>,Set<String>>();
-    for (Key<?> key : factories.keySet()) {
-      Set<String> names = map.get(key.getType());
-      if (names == null) {
-        names = new HashSet<String>();
-        map.put(key.getType(), names);
-      }
-      names.add(key.getName());
-    }
-    
-    for (Entry<Class<?>,Set<String>> entry : map.entrySet()) {
-      entry.setValue(Collections.unmodifiableSet(entry.getValue()));
-    }
-    
-    this.factoryNamesByType = Collections.unmodifiableMap(map);
-  }
-
-  @SuppressWarnings("unchecked")
-  <T> InternalFactory<? extends T> getFactory(Key<T> key) {
-    return (InternalFactory<T>) factories.get(key);
-  }
-
-  /**
-   * Field and method injectors.
-   */
-  final Map<Class<?>, List<Injector>> injectors =
-      new ReferenceCache<Class<?>, List<Injector>>() {
-        @Override
-        protected List<Injector> create(Class<?> key) {
-          List<Injector> injectors = new ArrayList<Injector>();
-          addInjectors(key, injectors);
-          return injectors;
-        }
-      };
-
-  /**
-   * Recursively adds injectors for fields and methods from the given class to
-   * the given list. Injects parent classes before sub classes.
-   */
-  void addInjectors(Class clazz, List<Injector> injectors) {
-    if (clazz == Object.class) {
-      return;
-    }
-
-    // Add injectors for superclass first.
-    addInjectors(clazz.getSuperclass(), injectors);
-
-    // TODO (crazybob): Filter out overridden members.
-    addInjectorsForFields(clazz.getDeclaredFields(), false, injectors);
-    addInjectorsForMethods(clazz.getDeclaredMethods(), false, injectors);
-  }
-
-  void injectStatics(List<Class<?>> staticInjections) {
-    final List<Injector> injectors = new ArrayList<Injector>();
-
-    for (Class<?> clazz : staticInjections) {
-      addInjectorsForFields(clazz.getDeclaredFields(), true, injectors);
-      addInjectorsForMethods(clazz.getDeclaredMethods(), true, injectors);
-    }
-
-    callInContext(new ContextualCallable<Void>() {
-      public Void call(InternalContext context) {
-        for (Injector injector : injectors) {
-          injector.inject(context, null);
-        }
-        return null;
-      }
-    });
-  }
-
-  void addInjectorsForMethods(Method[] methods, boolean statics,
-      List<Injector> injectors) {
-    addInjectorsForMembers(Arrays.asList(methods), statics, injectors,
-        new InjectorFactory<Method>() {
-          public Injector create(ContainerImpl container, Method method,
-              String name) throws MissingDependencyException {
-            return new MethodInjector(container, method, name);
-          }
-        });
-  }
-
-  void addInjectorsForFields(Field[] fields, boolean statics,
-      List<Injector> injectors) {
-    addInjectorsForMembers(Arrays.asList(fields), statics, injectors,
-        new InjectorFactory<Field>() {
-          public Injector create(ContainerImpl container, Field field,
-              String name) throws MissingDependencyException {
-            return new FieldInjector(container, field, name);
-          }
-        });
-  }
-
-  <M extends Member & AnnotatedElement> void addInjectorsForMembers(
-      List<M> members, boolean statics, List<Injector> injectors,
-      InjectorFactory<M> injectorFactory) {
-    for (M member : members) {
-      if (isStatic(member) == statics) {
-        Inject inject = member.getAnnotation(Inject.class);
-        if (inject != null) {
-          try {
-            injectors.add(injectorFactory.create(this, member, 
inject.value()));
-          } catch (MissingDependencyException e) {
-            if (inject.required()) {
-              throw new DependencyException(e);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  interface InjectorFactory<M extends Member & AnnotatedElement> {
-    Injector create(ContainerImpl container, M member, String name)
-        throws MissingDependencyException;
-  }
-
-  private boolean isStatic(Member member) {
-    return Modifier.isStatic(member.getModifiers());
-  }
-
-  static class FieldInjector implements Injector {
-
-    final Field field;
-    final InternalFactory<?> factory;
-    final ExternalContext<?> externalContext;
-
-    public FieldInjector(ContainerImpl container, Field field, String name)
-        throws MissingDependencyException {
-      this.field = field;
-        if (!field.isAccessible()) {
-            SecurityManager sm = System.getSecurityManager();
-            try {
-                if (sm != null) sm.checkPermission(new 
ReflectPermission("suppressAccessChecks"));
-                field.setAccessible(true);
-            } catch(AccessControlException e) {
-                throw new DependencyException("Security manager in use, could 
not access field: "
-                        + field.getDeclaringClass().getName() + "(" + 
field.getName() + ")", e);
-            }
-        }
-
-      Key<?> key = Key.newInstance(field.getType(), name);
-      factory = container.getFactory(key);
-      if (factory == null) {
-        throw new MissingDependencyException(
-            "No mapping found for dependency " + key + " in " + field + ".");
-      }
-
-      this.externalContext = ExternalContext.newInstance(field, key, 
container);
-    }
-
-    public void inject(InternalContext context, Object o) {
-      ExternalContext<?> previous = context.getExternalContext();
-      context.setExternalContext(externalContext);
-      try {
-        field.set(o, factory.create(context));
-      } catch (IllegalAccessException e) {
-        throw new AssertionError(e);
-      } finally {
-        context.setExternalContext(previous);
-      }
-    }
-  }
-
-  /**
-   * Gets parameter injectors.
-   *
-   * @param member to which the parameters belong
-   * @param annotations on the parameters
-   * @param parameterTypes parameter types
-   * @return injections
-   */
-  <M extends AccessibleObject & Member> ParameterInjector<?>[]
-      getParametersInjectors(M member,
-      Annotation[][] annotations, Class[] parameterTypes, String defaultName)
-      throws MissingDependencyException {
-    List<ParameterInjector<?>> parameterInjectors =
-        new ArrayList<ParameterInjector<?>>();
-
-    Iterator<Annotation[]> annotationsIterator =
-        Arrays.asList(annotations).iterator();
-    for (Class<?> parameterType : parameterTypes) {
-      Inject annotation = findInject(annotationsIterator.next());
-      String name = annotation == null ? defaultName : annotation.value();
-      Key<?> key = Key.newInstance(parameterType, name);
-      parameterInjectors.add(createParameterInjector(key, member));
-    }
-
-    return toArray(parameterInjectors);
-  }
-
-  <T> ParameterInjector<T> createParameterInjector(
-      Key<T> key, Member member) throws MissingDependencyException {
-    InternalFactory<? extends T> factory = getFactory(key);
-    if (factory == null) {
-      throw new MissingDependencyException(
-          "No mapping found for dependency " + key + " in " + member + ".");
-    }
-
-    ExternalContext<T> externalContext =
-        ExternalContext.newInstance(member, key, this);
-    return new ParameterInjector<T>(externalContext, factory);
-  }
-
-  @SuppressWarnings("unchecked")
-  private ParameterInjector<?>[] toArray(
-      List<ParameterInjector<?>> parameterInjections) {
-    return parameterInjections.toArray(
-        new ParameterInjector[parameterInjections.size()]);
-  }
-
-  /**
-   * Finds the {@link Inject} annotation in an array of annotations.
-   */
-  Inject findInject(Annotation[] annotations) {
-    for (Annotation annotation : annotations) {
-      if (annotation.annotationType() == Inject.class) {
-        return Inject.class.cast(annotation);
-      }
-    }
-    return null;
-  }
-
-  static class MethodInjector implements Injector {
-
-    final Method method;
-    final ParameterInjector<?>[] parameterInjectors;
-
-    public MethodInjector(ContainerImpl container, Method method, String name)
-        throws MissingDependencyException {
-      this.method = method;
-        if (!method.isAccessible()) {
-            SecurityManager sm = System.getSecurityManager();
-            try {
-                if (sm != null) sm.checkPermission(new 
ReflectPermission("suppressAccessChecks"));
-                method.setAccessible(true);
-            } catch(AccessControlException e) {
-                throw new DependencyException("Security manager in use, could 
not access method: "
-                        + name + "(" + method.getName() + ")", e);
-            }
-        }
-
-      Class<?>[] parameterTypes = method.getParameterTypes();
-      if (parameterTypes.length == 0) {
-        throw new DependencyException(
-            method + " has no parameters to inject.");
-      }
-      parameterInjectors = container.getParametersInjectors(
-          method, method.getParameterAnnotations(), parameterTypes, name);
-    }
-
-    public void inject(InternalContext context, Object o) {
-      try {
-        method.invoke(o, getParameters(method, context, parameterInjectors));
-      } catch (Exception e) {
-        throw new RuntimeException(e);
-      }
-    }
-  }
-
-  Map<Class<?>, ConstructorInjector> constructors =
-      new ReferenceCache<Class<?>, ConstructorInjector>() {
-        @Override
-        @SuppressWarnings("unchecked")
-        protected ConstructorInjector<?> create(Class<?> implementation) {
-          return new ConstructorInjector(ContainerImpl.this, implementation);
-        }
-      };
-
-  static class ConstructorInjector<T> {
-
-    final Class<T> implementation;
-    final List<Injector> injectors;
-    final Constructor<T> constructor;
-    final ParameterInjector<?>[] parameterInjectors;
-
-    ConstructorInjector(ContainerImpl container, Class<T> implementation) {
-      this.implementation = implementation;
-
-      constructor = findConstructorIn(implementation);
-        if (!constructor.isAccessible()) {
-            SecurityManager sm = System.getSecurityManager();
-            try {
-                if (sm != null) sm.checkPermission(new 
ReflectPermission("suppressAccessChecks"));
-                constructor.setAccessible(true);
-            } catch(AccessControlException e) {
-                throw new DependencyException("Security manager in use, could 
not access constructor: "
-                        + implementation.getName() + "(" + 
constructor.getName() + ")", e);
-            }
-        }
-
-      MissingDependencyException exception = null;
-      Inject inject = null;
-      ParameterInjector<?>[] parameters = null;
-        
-      try {
-        inject = constructor.getAnnotation(Inject.class);
-        parameters = constructParameterInjector(inject, container, 
constructor);
-      } catch (MissingDependencyException e) {
-        exception = e;
-      }
-      parameterInjectors = parameters;
-
-      if ( exception != null) {
-        if ( inject != null && inject.required()) {
-          throw new DependencyException(exception);
-        }
-      }
-      injectors = container.injectors.get(implementation);
-    }
-
-    ParameterInjector<?>[] constructParameterInjector(
-    Inject inject, ContainerImpl container, Constructor<T> constructor) throws 
MissingDependencyException{
-    return constructor.getParameterTypes().length == 0
-      ? null // default constructor.
-      : container.getParametersInjectors(
-        constructor,
-        constructor.getParameterAnnotations(),
-        constructor.getParameterTypes(),
-        inject.value()
-      );
-    }
-
-    @SuppressWarnings("unchecked")
-    private Constructor<T> findConstructorIn(Class<T> implementation) {
-      Constructor<T> found = null;
-      Constructor<T>[] declaredConstructors = (Constructor<T>[]) implementation
-                    .getDeclaredConstructors();
-      for(Constructor<T> constructor :  declaredConstructors) {
-        if (constructor.getAnnotation(Inject.class) != null) {
-          if (found != null) {
-            throw new DependencyException("More than one constructor annotated"
-              + " with @Inject found in " + implementation + ".");
-          }
-          found = constructor;
-        }
-      }
-      if (found != null) {
-        return found;
-      }
-
-      // If no annotated constructor is found, look for a no-arg constructor
-      // instead.
-      try {
-        return implementation.getDeclaredConstructor();
-      } catch (NoSuchMethodException e) {
-        throw new DependencyException("Could not find a suitable constructor"
-            + " in " + implementation.getName() + ".");
-      }
-    }
-
-    /**
-     * Construct an instance. Returns {@code Object} instead of {@code T}
-     * because it may return a proxy.
-     */
-    Object construct(InternalContext context, Class<? super T> expectedType) {
-      ConstructionContext<T> constructionContext =
-          context.getConstructionContext(this);
-
-      // We have a circular reference between constructors. Return a proxy.
-      if (constructionContext.isConstructing()) {
-        // TODO (crazybob): if we can't proxy this object, can we proxy the
-        // other object?
-        return constructionContext.createProxy(expectedType);
-      }
-
-      // If we're re-entering this factory while injecting fields or methods,
-      // return the same instance. This prevents infinite loops.
-      T t = constructionContext.getCurrentReference();
-      if (t != null) {
-        return t;
-      }
-
-      try {
-        // First time through...
-        constructionContext.startConstruction();
-        try {
-          Object[] parameters =
-              getParameters(constructor, context, parameterInjectors);
-          t = constructor.newInstance(parameters);
-          constructionContext.setProxyDelegates(t);
-        } finally {
-          constructionContext.finishConstruction();
-        }
-
-        // Store reference. If an injector re-enters this factory, they'll
-        // get the same reference.
-        constructionContext.setCurrentReference(t);
-
-        // Inject fields and methods.
-        for (Injector injector : injectors) {
-          injector.inject(context, t);
-        }
-
-        return t;
-      } catch (InstantiationException e) {
-        throw new RuntimeException(e);
-      } catch (IllegalAccessException e) {
-        throw new RuntimeException(e);
-      } catch (InvocationTargetException e) {
-        throw new RuntimeException(e);
-      } finally {
-        constructionContext.removeCurrentReference();
-      }
-    }
-  }
-
-  static class ParameterInjector<T> {
-
-    final ExternalContext<T> externalContext;
-    final InternalFactory<? extends T> factory;
-
-    public ParameterInjector(ExternalContext<T> externalContext,
-        InternalFactory<? extends T> factory) {
-      this.externalContext = externalContext;
-      this.factory = factory;
-    }
-
-    T inject(Member member, InternalContext context) {
-      ExternalContext<?> previous = context.getExternalContext();
-      context.setExternalContext(externalContext);
-      try {
-        return factory.create(context);
-      } finally {
-        context.setExternalContext(previous);
-      }
-    }
-  }
-
-  private static Object[] getParameters(Member member, InternalContext context,
-      ParameterInjector[] parameterInjectors) {
-    if (parameterInjectors == null) {
-      return null;
-    }
-
-    Object[] parameters = new Object[parameterInjectors.length];
-    for (int i = 0; i < parameters.length; i++) {
-      parameters[i] = parameterInjectors[i].inject(member, context);
-    }
-    return parameters;
-  }
-
-  void inject(Object o, InternalContext context) {
-    List<Injector> injectors = this.injectors.get(o.getClass());
-    for (Injector injector : injectors) {
-      injector.inject(context, o);
-    }
-  }
-
-  <T> T inject(Class<T> implementation, InternalContext context) {
-    try {
-      ConstructorInjector<T> constructor = getConstructor(implementation);
-      return implementation.cast(
-          constructor.construct(context, implementation));
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  @SuppressWarnings("unchecked")
-  <T> T getInstance(Class<T> type, String name, InternalContext context) {
-    ExternalContext<?> previous = context.getExternalContext();
-    Key<T> key = Key.newInstance(type, name);
-    context.setExternalContext(ExternalContext.newInstance(null, key, this));
-    try {
-      InternalFactory o = getFactory(key);
-      if (o != null) {
-          return getFactory(key).create(context);
-      } else {
-          return null;
-      }
-    } finally {
-      context.setExternalContext(previous);
-    }
-  }
-
-  <T> T getInstance(Class<T> type, InternalContext context) {
-    return getInstance(type, DEFAULT_NAME, context);
-  }
-
-  public void inject(final Object o) {
-    callInContext(new ContextualCallable<Void>() {
-      public Void call(InternalContext context) {
-        inject(o, context);
-        return null;
-      }
-    });
-  }
-
-  public <T> T inject(final Class<T> implementation) {
-    return callInContext(new ContextualCallable<T>() {
-      public T call(InternalContext context) {
-        return inject(implementation, context);
-      }
-    });
-  }
-
-  public <T> T getInstance(final Class<T> type, final String name) {
-    return callInContext(new ContextualCallable<T>() {
-      public T call(InternalContext context) {
-        return getInstance(type, name, context);
-      }
-    });
-  }
-
-  public <T> T getInstance(final Class<T> type) {
-    return callInContext(new ContextualCallable<T>() {
-      public T call(InternalContext context) {
-        return getInstance(type, context);
-      }
-    });
-  }
-  
-  public Set<String> getInstanceNames(final Class<?> type) {
-    return factoryNamesByType.get(type);
-  }
-
-  ThreadLocal<Object[]> localContext =
-      new ThreadLocal<Object[]>() {
-        @Override
-        protected Object[] initialValue() {
-          return new Object[1];
-        }
-      };
-
-  /**
-   * Looks up thread local context. Creates (and removes) a new context if
-   * necessary.
-   */
-  <T> T callInContext(ContextualCallable<T> callable) {
-    Object[] reference = localContext.get();
-    if (reference[0] == null) {
-      reference[0] = new InternalContext(this);
-      try {
-        return callable.call((InternalContext)reference[0]);
-      } finally {
-        // Only remove the context if this call created it.
-        reference[0] = null;
-      }
-    } else {
-      // Someone else will clean up this context.
-      return callable.call((InternalContext)reference[0]);
-    }
-  }
-
-  interface ContextualCallable<T> {
-    T call(InternalContext context);
-  }
-
-  /**
-   * Gets a constructor function for a given implementation class.
-   */
-  @SuppressWarnings("unchecked")
-  <T> ConstructorInjector<T> getConstructor(Class<T> implementation) {
-    return constructors.get(implementation);
-  }
-
-  final ThreadLocal<Object> localScopeStrategy =
-      new ThreadLocal<Object>();
-
-  public void setScopeStrategy(Scope.Strategy scopeStrategy) {
-    this.localScopeStrategy.set(scopeStrategy);
-  }
-
-  public void removeScopeStrategy() {
-    this.localScopeStrategy.remove();
-  }
-
-  /**
-   * Injects a field or method in a given object.
-   */
-  interface Injector extends Serializable {
-    void inject(InternalContext context, Object o);
-  }
-
-  static class MissingDependencyException extends Exception {
-
-    MissingDependencyException(String message) {
-      super(message);
-    }
-  }
+       ContainerImpl( Map<Key<?>, InternalFactory<?>> factories ) {
+               this.factories = factories;
+               Map<Class<?>, Set<String>> map = new HashMap<Class<?>, 
Set<String>>();
+               for ( Key<?> key : factories.keySet() ) {
+                       Set<String> names = map.get(key.getType());
+                       if (names == null) {
+                               names = new HashSet<String>();
+                               map.put(key.getType(), names);
+                       }
+                       names.add(key.getName());
+               }
+
+               for ( Entry<Class<?>, Set<String>> entry : map.entrySet() ) {
+                       
entry.setValue(Collections.unmodifiableSet(entry.getValue()));
+               }
+
+               this.factoryNamesByType = Collections.unmodifiableMap(map);
+       }
+
+       @SuppressWarnings("unchecked")
+       <T> InternalFactory<? extends T> getFactory( Key<T> key ) {
+               return (InternalFactory<T>) factories.get(key);
+       }
+
+       /**
+        * Field and method injectors.
+        */
+       final Map<Class<?>, List<Injector>> injectors =
+                       new ReferenceCache<Class<?>, List<Injector>>() {
+                               @Override
+                               protected List<Injector> create( Class<?> key ) 
{
+                                       List<Injector> injectors = new 
ArrayList<Injector>();
+                                       addInjectors(key, injectors);
+                                       return injectors;
+                               }
+                       };
+
+       /**
+        * Recursively adds injectors for fields and methods from the given 
class to the given list. Injects parent classes
+        * before sub classes.
+        */
+       void addInjectors( Class clazz, List<Injector> injectors ) {
+               if (clazz == Object.class) {
+                       return;
+               }
+
+               // Add injectors for superclass first.
+               addInjectors(clazz.getSuperclass(), injectors);
+
+               // TODO (crazybob): Filter out overridden members.
+               addInjectorsForFields(clazz.getDeclaredFields(), false, 
injectors);
+               addInjectorsForMethods(clazz.getDeclaredMethods(), false, 
injectors);
+       }
+
+       void injectStatics( List<Class<?>> staticInjections ) {
+               final List<Injector> injectors = new ArrayList<Injector>();
+
+               for ( Class<?> clazz : staticInjections ) {
+                       addInjectorsForFields(clazz.getDeclaredFields(), true, 
injectors);
+                       addInjectorsForMethods(clazz.getDeclaredMethods(), 
true, injectors);
+               }
+
+               callInContext(new ContextualCallable<Void>() {
+                       public Void call( InternalContext context ) {
+                               for ( Injector injector : injectors ) {
+                                       injector.inject(context, null);
+                               }
+                               return null;
+                       }
+               });
+       }
+
+       void addInjectorsForMethods( Method[] methods, boolean statics,
+                                                                List<Injector> 
injectors ) {
+               addInjectorsForMembers(Arrays.asList(methods), statics, 
injectors,
+                               new InjectorFactory<Method>() {
+                                       public Injector create( ContainerImpl 
container, Method method,
+                                                                               
        String name ) throws MissingDependencyException {
+                                               return new 
MethodInjector(container, method, name);
+                                       }
+                               });
+       }
+
+       void addInjectorsForFields( Field[] fields, boolean statics,
+                                                               List<Injector> 
injectors ) {
+               addInjectorsForMembers(Arrays.asList(fields), statics, 
injectors,
+                               new InjectorFactory<Field>() {
+                                       public Injector create( ContainerImpl 
container, Field field,
+                                                                               
        String name ) throws MissingDependencyException {
+                                               return new 
FieldInjector(container, field, name);
+                                       }
+                               });
+       }
+
+       <M extends Member & AnnotatedElement> void addInjectorsForMembers(
+                       List<M> members, boolean statics, List<Injector> 
injectors,
+                       InjectorFactory<M> injectorFactory ) {
+               for ( M member : members ) {
+                       if (isStatic(member) == statics) {
+                               Inject inject = 
member.getAnnotation(Inject.class);
+                               if (inject != null) {
+                                       try {
+                                               
injectors.add(injectorFactory.create(this, member, inject.value()));
+                                       } catch ( MissingDependencyException e 
) {
+                                               if (inject.required()) {
+                                                       throw new 
DependencyException(e);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       interface InjectorFactory<M extends Member & AnnotatedElement> {
+
+               Injector create( ContainerImpl container, M member, String name 
)
+                               throws MissingDependencyException;
+       }
+
+       private boolean isStatic( Member member ) {
+               return Modifier.isStatic(member.getModifiers());
+       }
+
+       static class FieldInjector implements Injector {
+
+               final Field field;
+               final InternalFactory<?> factory;
+               final ExternalContext<?> externalContext;
+
+               public FieldInjector( ContainerImpl container, Field field, 
String name )
+                               throws MissingDependencyException {
+                       this.field = field;
+                       if (!field.isAccessible()) {
+                               SecurityManager sm = 
System.getSecurityManager();
+                               try {
+                                       if (sm != null) {
+                                               sm.checkPermission(new 
ReflectPermission("suppressAccessChecks"));
+                                       }
+                                       field.setAccessible(true);
+                               } catch ( AccessControlException e ) {
+                                       throw new DependencyException("Security 
manager in use, could not access field: "
+                                                       + 
field.getDeclaringClass().getName() + "(" + field.getName() + ")", e);
+                               }
+                       }
+
+                       Key<?> key = Key.newInstance(field.getType(), name);
+                       factory = container.getFactory(key);
+                       if (factory == null) {
+                               throw new MissingDependencyException(
+                                               "No mapping found for 
dependency " + key + " in " + field + ".");
+                       }
+
+                       this.externalContext = 
ExternalContext.newInstance(field, key, container);
+               }
+
+               public void inject( InternalContext context, Object o ) {
+                       ExternalContext<?> previous = 
context.getExternalContext();
+                       context.setExternalContext(externalContext);
+                       try {
+                               field.set(o, factory.create(context));
+                       } catch ( IllegalAccessException e ) {
+                               throw new AssertionError(e);
+                       } finally {
+                               context.setExternalContext(previous);
+                       }
+               }
+       }
+
+       /**
+        * Gets parameter injectors.
+        *
+        * @param member                 to which the parameters belong
+        * @param annotations   on the parameters
+        * @param parameterTypes parameter types
+        *
+        * @return injections
+        */
+       <M extends AccessibleObject & Member> ParameterInjector<?>[]
+       getParametersInjectors( M member,
+                                                       Annotation[][] 
annotations, Class[] parameterTypes, String defaultName )
+                       throws MissingDependencyException {
+               List<ParameterInjector<?>> parameterInjectors =
+                               new ArrayList<ParameterInjector<?>>();
+
+               Iterator<Annotation[]> annotationsIterator =
+                               Arrays.asList(annotations).iterator();
+               for ( Class<?> parameterType : parameterTypes ) {
+                       Inject annotation = 
findInject(annotationsIterator.next());
+                       String name = annotation == null ? defaultName : 
annotation.value();
+                       Key<?> key = Key.newInstance(parameterType, name);
+                       parameterInjectors.add(createParameterInjector(key, 
member));
+               }
+
+               return toArray(parameterInjectors);
+       }
+
+       <T> ParameterInjector<T> createParameterInjector(
+                       Key<T> key, Member member ) throws 
MissingDependencyException {
+               InternalFactory<? extends T> factory = getFactory(key);
+               if (factory == null) {
+                       throw new MissingDependencyException(
+                                       "No mapping found for dependency " + 
key + " in " + member + ".");
+               }
+
+               ExternalContext<T> externalContext =
+                               ExternalContext.newInstance(member, key, this);
+               return new ParameterInjector<T>(externalContext, factory);
+       }
+
+       @SuppressWarnings("unchecked")
+       private ParameterInjector<?>[] toArray(
+                       List<ParameterInjector<?>> parameterInjections ) {
+               return parameterInjections.toArray(
+                               new 
ParameterInjector[parameterInjections.size()]);
+       }
+
+       /**
+        * Finds the {@link Inject} annotation in an array of annotations.
+        */
+       Inject findInject( Annotation[] annotations ) {
+               for ( Annotation annotation : annotations ) {
+                       if (annotation.annotationType() == Inject.class) {
+                               return Inject.class.cast(annotation);
+                       }
+               }
+               return null;
+       }
+
+       static class MethodInjector implements Injector {
+
+               final Method method;
+               final ParameterInjector<?>[] parameterInjectors;
+
+               public MethodInjector( ContainerImpl container, Method method, 
String name )
+                               throws MissingDependencyException {
+                       this.method = method;
+                       if (!method.isAccessible()) {
+                               SecurityManager sm = 
System.getSecurityManager();
+                               try {
+                                       if (sm != null) {
+                                               sm.checkPermission(new 
ReflectPermission("suppressAccessChecks"));
+                                       }
+                                       method.setAccessible(true);
+                               } catch ( AccessControlException e ) {
+                                       throw new DependencyException("Security 
manager in use, could not access method: "
+                                                       + name + "(" + 
method.getName() + ")", e);
+                               }
+                       }
+
+                       Class<?>[] parameterTypes = method.getParameterTypes();
+                       if (parameterTypes.length == 0) {
+                               throw new DependencyException(
+                                               method + " has no parameters to 
inject.");
+                       }
+                       parameterInjectors = container.getParametersInjectors(
+                                       method, 
method.getParameterAnnotations(), parameterTypes, name);
+               }
+
+               public void inject( InternalContext context, Object o ) {
+                       try {
+                               method.invoke(o, getParameters(method, context, 
parameterInjectors));
+                       } catch ( Exception e ) {
+                               throw new RuntimeException(e);
+                       }
+               }
+       }
+
+       Map<Class<?>, ConstructorInjector> constructors =
+                       new ReferenceCache<Class<?>, ConstructorInjector>() {
+                               @Override
+                               @SuppressWarnings("unchecked")
+                               protected ConstructorInjector<?> create( 
Class<?> implementation ) {
+                                       return new 
ConstructorInjector(ContainerImpl.this, implementation);
+                               }
+                       };
+
+       static class ConstructorInjector<T> {
+
+               final Class<T> implementation;
+               final List<Injector> injectors;
+               final Constructor<T> constructor;
+               final ParameterInjector<?>[] parameterInjectors;
+
+               ConstructorInjector( ContainerImpl container, Class<T> 
implementation ) {
+                       this.implementation = implementation;
+
+                       constructor = findConstructorIn(implementation);
+                       if (!constructor.isAccessible()) {
+                               SecurityManager sm = 
System.getSecurityManager();
+                               try {
+                                       if (sm != null) {
+                                               sm.checkPermission(new 
ReflectPermission("suppressAccessChecks"));
+                                       }
+                                       constructor.setAccessible(true);
+                               } catch ( AccessControlException e ) {
+                                       throw new DependencyException("Security 
manager in use, could not access constructor: "
+                                                       + 
implementation.getName() + "(" + constructor.getName() + ")", e);
+                               }
+                       }
+
+                       MissingDependencyException exception = null;
+                       Inject inject = null;
+                       ParameterInjector<?>[] parameters = null;
+
+                       try {
+                               inject = 
constructor.getAnnotation(Inject.class);
+                               parameters = constructParameterInjector(inject, 
container, constructor);
+                       } catch ( MissingDependencyException e ) {
+                               exception = e;
+                       }
+                       parameterInjectors = parameters;
+
+                       if (exception != null) {
+                               if (inject != null && inject.required()) {
+                                       throw new 
DependencyException(exception);
+                               }
+                       }
+                       injectors = container.injectors.get(implementation);
+               }
+
+               ParameterInjector<?>[] constructParameterInjector(
+                               Inject inject, ContainerImpl container, 
Constructor<T> constructor ) throws MissingDependencyException {
+                       return constructor.getParameterTypes().length == 0
+                                       ? null // default constructor.
+                                       : container.getParametersInjectors(
+                                       constructor,
+                                       constructor.getParameterAnnotations(),
+                                       constructor.getParameterTypes(),
+                                       inject.value()
+                       );
+               }
+
+               @SuppressWarnings("unchecked")
+               private Constructor<T> findConstructorIn( Class<T> 
implementation ) {
+                       Constructor<T> found = null;
+                       Constructor<T>[] declaredConstructors = 
(Constructor<T>[]) implementation
+                                       .getDeclaredConstructors();
+                       for ( Constructor<T> constructor : declaredConstructors 
) {
+                               if (constructor.getAnnotation(Inject.class) != 
null) {
+                                       if (found != null) {
+                                               throw new 
DependencyException("More than one constructor annotated"
+                                                               + " with 
@Inject found in " + implementation + ".");
+                                       }
+                                       found = constructor;
+                               }
+                       }
+                       if (found != null) {
+                               return found;
+                       }
+
+                       // If no annotated constructor is found, look for a 
no-arg constructor
+                       // instead.
+                       try {
+                               return implementation.getDeclaredConstructor();
+                       } catch ( NoSuchMethodException e ) {
+                               throw new DependencyException("Could not find a 
suitable constructor"
+                                               + " in " + 
implementation.getName() + ".");
+                       }
+               }
+
+               /**
+                * Construct an instance. Returns {@code Object} instead of 
{@code T} because it may return a proxy.
+                */
+               Object construct( InternalContext context, Class<? super T> 
expectedType ) {
+                       ConstructionContext<T> constructionContext =
+                                       context.getConstructionContext(this);
+
+                       // We have a circular reference between constructors. 
Return a proxy.
+                       if (constructionContext.isConstructing()) {
+                               // TODO (crazybob): if we can't proxy this 
object, can we proxy the
+                               // other object?
+                               return 
constructionContext.createProxy(expectedType);
+                       }
+
+                       // If we're re-entering this factory while injecting 
fields or methods,
+                       // return the same instance. This prevents infinite 
loops.
+                       T t = constructionContext.getCurrentReference();
+                       if (t != null) {
+                               return t;
+                       }
+
+                       try {
+                               // First time through...
+                               constructionContext.startConstruction();
+                               try {
+                                       Object[] parameters =
+                                                       
getParameters(constructor, context, parameterInjectors);
+                                       t = constructor.newInstance(parameters);
+                                       
constructionContext.setProxyDelegates(t);
+                               } finally {
+                                       
constructionContext.finishConstruction();
+                               }
+
+                               // Store reference. If an injector re-enters 
this factory, they'll
+                               // get the same reference.
+                               constructionContext.setCurrentReference(t);
+
+                               // Inject fields and methods.
+                               for ( Injector injector : injectors ) {
+                                       injector.inject(context, t);
+                               }
+
+                               return t;
+                       } catch ( InstantiationException e ) {
+                               throw new RuntimeException(e);
+                       } catch ( IllegalAccessException e ) {
+                               throw new RuntimeException(e);
+                       } catch ( InvocationTargetException e ) {
+                               throw new RuntimeException(e);
+                       } finally {
+                               constructionContext.removeCurrentReference();
+                       }
+               }
+       }
+
+       static class ParameterInjector<T> {
+
+               final ExternalContext<T> externalContext;
+               final InternalFactory<? extends T> factory;
+
+               public ParameterInjector( ExternalContext<T> externalContext,
+                                                                 
InternalFactory<? extends T> factory ) {
+                       this.externalContext = externalContext;
+                       this.factory = factory;
+               }
+
+               T inject( Member member, InternalContext context ) {
+                       ExternalContext<?> previous = 
context.getExternalContext();
+                       context.setExternalContext(externalContext);
+                       try {
+                               return factory.create(context);
+                       } finally {
+                               context.setExternalContext(previous);
+                       }
+               }
+       }
+
+       private static Object[] getParameters( Member member, InternalContext 
context,
+                                                                               
   ParameterInjector[] parameterInjectors ) {
+               if (parameterInjectors == null) {
+                       return null;
+               }
+
+               Object[] parameters = new Object[parameterInjectors.length];
+               for ( int i = 0; i < parameters.length; i++ ) {
+                       parameters[i] = parameterInjectors[i].inject(member, 
context);
+               }
+               return parameters;
+       }
+
+       void inject( Object o, InternalContext context ) {
+               List<Injector> injectors = this.injectors.get(o.getClass());
+               for ( Injector injector : injectors ) {
+                       injector.inject(context, o);
+               }
+       }
+
+       <T> T inject( Class<T> implementation, InternalContext context ) {
+               try {
+                       ConstructorInjector<T> constructor = 
getConstructor(implementation);
+                       return implementation.cast(
+                                       constructor.construct(context, 
implementation));
+               } catch ( Exception e ) {
+                       throw new RuntimeException(e);
+               }
+       }
+
+       @SuppressWarnings("unchecked")
+       <T> T getInstance( Class<T> type, String name, InternalContext context 
) {
+               ExternalContext<?> previous = context.getExternalContext();
+               Key<T> key = Key.newInstance(type, name);
+               context.setExternalContext(ExternalContext.newInstance(null, 
key, this));
+               try {
+                       InternalFactory o = getFactory(key);
+                       if (o != null) {
+                               return getFactory(key).create(context);
+                       } else {
+                               return null;
+                       }
+               } finally {
+                       context.setExternalContext(previous);
+               }
+       }
+
+       <T> T getInstance( Class<T> type, InternalContext context ) {
+               return getInstance(type, DEFAULT_NAME, context);
+       }
+
+       public void inject( final Object o ) {
+               callInContext(new ContextualCallable<Void>() {
+                       public Void call( InternalContext context ) {
+                               inject(o, context);
+                               return null;
+                       }
+               });
+       }
+
+       public <T> T inject( final Class<T> implementation ) {
+               return callInContext(new ContextualCallable<T>() {
+                       public T call( InternalContext context ) {
+                               return inject(implementation, context);
+                       }
+               });
+       }
+
+       public <T> T getInstance( final Class<T> type, final String name ) {
+               return callInContext(new ContextualCallable<T>() {
+                       public T call( InternalContext context ) {
+                               return getInstance(type, name, context);
+                       }
+               });
+       }
+
+       public <T> T getInstance( final Class<T> type ) {
+               return callInContext(new ContextualCallable<T>() {
+                       public T call( InternalContext context ) {
+                               return getInstance(type, context);
+                       }
+               });
+       }
+
+       public Set<String> getInstanceNames( final Class<?> type ) {
+               return factoryNamesByType.get(type);
+       }
+
+       ThreadLocal<Object[]> localContext =
+                       new ThreadLocal<Object[]>() {
+                               @Override
+                               protected Object[] initialValue() {
+                                       return new Object[1];
+                               }
+                       };
+
+       /**
+        * Looks up thread local context. Creates (and removes) a new context 
if necessary.
+        */
+       <T> T callInContext( ContextualCallable<T> callable ) {
+               Object[] reference = localContext.get();
+               if (reference[0] == null) {
+                       reference[0] = new InternalContext(this);
+                       try {
+                               return callable.call((InternalContext) 
reference[0]);
+                       } finally {
+                               // Only remove the context if this call created 
it.
+                               reference[0] = null;
+                       }
+               } else {
+                       // Someone else will clean up this context.
+                       return callable.call((InternalContext) reference[0]);
+               }
+       }
+
+       interface ContextualCallable<T> {
+
+               T call( InternalContext context );
+       }
+
+       /**
+        * Gets a constructor function for a given implementation class.
+        */
+       @SuppressWarnings("unchecked")
+       <T> ConstructorInjector<T> getConstructor( Class<T> implementation ) {
+               return constructors.get(implementation);
+       }
+
+       final ThreadLocal<Object> localScopeStrategy =
+                       new ThreadLocal<Object>();
+
+       public void setScopeStrategy( Scope.Strategy scopeStrategy ) {
+               this.localScopeStrategy.set(scopeStrategy);
+       }
+
+       public void removeScopeStrategy() {
+               this.localScopeStrategy.remove();
+       }
+
+       /**
+        * Injects a field or method in a given object.
+        */
+       interface Injector extends Serializable {
+
+               void inject( InternalContext context, Object o );
+       }
+
+       static class MissingDependencyException extends Exception {
+
+               MissingDependencyException( String message ) {
+                       super(message);
+               }
+       }
 }


Reply via email to