struts-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jo...@apache.org
Subject [7/9] struts git commit: Minor code improvements's in the xwork-core module
Date Mon, 15 Jun 2015 17:38:08 GMT
http://git-wip-us.apache.org/repos/asf/struts/blob/2e9df577/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
----------------------------------------------------------------------
diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
index 1b9abb9..1879933 100644
--- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
+++ b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
@@ -1,12 +1,12 @@
 /**
  * Copyright (C) 2006 Google Inc.
- *
+ * <p/>
  * Licensed 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
- *
+ * <p/>
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
  * 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.
@@ -21,9 +21,9 @@ import com.opensymphony.xwork2.inject.util.ReferenceCache;
 import java.io.Serializable;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.*;
+import java.security.AccessControlException;
 import java.util.*;
 import java.util.Map.Entry;
-import java.security.AccessControlException;
 
 /**
  * Default {@link Container} implementation.
@@ -33,603 +33,571 @@ import java.security.AccessControlException;
  */
 class ContainerImpl implements Container {
 
-	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 ) {
+    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<>();
+        for (Key<?> key : factories.keySet()) {
+            Set<String> names = map.get(key.getType());
+            if (names == null) {
+                names = new HashSet<>();
+                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<>();
+                    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<>();
+
+        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<>();
+
+        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 | IllegalAccessException | 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) {
         Set<String> names = factoryNamesByType.get(type);
         if (names == null) {
             names = Collections.emptySet();
         }
         return names;
-	}
-
-	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;
-				// WW-3768: ThreadLocal was not removed
-				localContext.remove();
-			}
-		} 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);
-		}
-	}
+    }
+
+    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;
+                // WW-3768: ThreadLocal was not removed
+                localContext.remove();
+            }
+        } 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<>();
+
+    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);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/struts/blob/2e9df577/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ExternalContext.java
----------------------------------------------------------------------
diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ExternalContext.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ExternalContext.java
index 8a3880e..0c054e8 100644
--- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ExternalContext.java
+++ b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ExternalContext.java
@@ -1,12 +1,12 @@
 /**
  * Copyright (C) 2006 Google Inc.
- *
+ * <p/>
  * Licensed 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
- *
+ * <p/>
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
  * 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.
@@ -27,48 +27,47 @@ import java.util.LinkedHashMap;
  */
 class ExternalContext<T> implements Context {
 
-  final Member member;
-  final Key<T> key;
-  final ContainerImpl container;
+    final Member member;
+    final Key<T> key;
+    final ContainerImpl container;
 
-  public ExternalContext(Member member, Key<T> key, ContainerImpl container) {
-    this.member = member;
-    this.key = key;
-    this.container = container;
-  }
+    public ExternalContext(Member member, Key<T> key, ContainerImpl container) {
+        this.member = member;
+        this.key = key;
+        this.container = container;
+    }
 
-  public Class<T> getType() {
-    return key.getType();
-  }
+    public Class<T> getType() {
+        return key.getType();
+    }
 
-  public Scope.Strategy getScopeStrategy() {
-    return (Scope.Strategy) container.localScopeStrategy.get();
-  }
+    public Scope.Strategy getScopeStrategy() {
+        return (Scope.Strategy) container.localScopeStrategy.get();
+    }
 
-  public Container getContainer() {
-    return container;
-  }
+    public Container getContainer() {
+        return container;
+    }
 
-  public Member getMember() {
-    return member;
-  }
+    public Member getMember() {
+        return member;
+    }
 
-  public String getName() {
-    return key.getName();
-  }
+    public String getName() {
+        return key.getName();
+    }
 
-  @Override
-  public String toString() {
-    return "Context" + new LinkedHashMap<String, Object>() {{
-      put("member", member);
-      put("type", getType());
-      put("name", getName());
-      put("container", container);
-    }}.toString();
-  }
+    @Override
+    public String toString() {
+        return "Context" + new LinkedHashMap<String, Object>() {{
+            put("member", member);
+            put("type", getType());
+            put("name", getName());
+            put("container", container);
+        }}.toString();
+    }
 
-  static <T> ExternalContext<T> newInstance(Member member, Key<T> key,
-      ContainerImpl container) {
-    return new ExternalContext<T>(member, key, container);
-  }
+    static <T> ExternalContext<T> newInstance(Member member, Key<T> key, ContainerImpl container) {
+        return new ExternalContext<T>(member, key, container);
+    }
 }

http://git-wip-us.apache.org/repos/asf/struts/blob/2e9df577/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalContext.java
----------------------------------------------------------------------
diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalContext.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalContext.java
index 16fa0c1..7014480 100644
--- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalContext.java
+++ b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalContext.java
@@ -28,8 +28,7 @@ import java.util.Map;
 class InternalContext {
 
   final ContainerImpl container;
-  final Map<Object, ConstructionContext<?>> constructionContexts =
-      new HashMap<Object, ConstructionContext<?>>();
+  final Map<Object, ConstructionContext<?>> constructionContexts = new HashMap<Object, ConstructionContext<?>>();
   Scope.Strategy scopeStrategy;
   ExternalContext<?> externalContext;
 
@@ -50,8 +49,7 @@ class InternalContext {
       scopeStrategy = (Scope.Strategy) container.localScopeStrategy.get();
 
       if (scopeStrategy == null) {
-        throw new IllegalStateException("Scope strategy not set. "
-            + "Please call Container.setScopeStrategy().");
+        throw new IllegalStateException("Scope strategy not set. Please call Container.setScopeStrategy().");
       }
     }
 
@@ -60,8 +58,7 @@ class InternalContext {
 
   @SuppressWarnings("unchecked")
   <T> ConstructionContext<T> getConstructionContext(Object key) {
-    ConstructionContext<T> constructionContext =
-        (ConstructionContext<T>) constructionContexts.get(key);
+    ConstructionContext<T> constructionContext = (ConstructionContext<T>) constructionContexts.get(key);
     if (constructionContext == null) {
       constructionContext = new ConstructionContext<T>();
       constructionContexts.put(key, constructionContext);

http://git-wip-us.apache.org/repos/asf/struts/blob/2e9df577/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Key.java
----------------------------------------------------------------------
diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Key.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Key.java
index 03756b9..ad9e0ba 100644
--- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Key.java
+++ b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Key.java
@@ -1,12 +1,12 @@
 /**
  * Copyright (C) 2006 Google Inc.
- *
+ * <p/>
  * Licensed 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
- *
+ * <p/>
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
  * 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.
@@ -23,55 +23,55 @@ package com.opensymphony.xwork2.inject;
  */
 class Key<T> {
 
-  final Class<T> type;
-  final String name;
-  final int hashCode;
-
-  private Key(Class<T> type, String name) {
-    if (type == null) {
-      throw new NullPointerException("Type is null.");
-    }
-    if (name == null) {
-      throw new NullPointerException("Name is null.");
-    }
+    final Class<T> type;
+    final String name;
+    final int hashCode;
 
-    this.type = type;
-    this.name = name;
+    private Key(Class<T> type, String name) {
+        if (type == null) {
+            throw new NullPointerException("Type is null.");
+        }
+        if (name == null) {
+            throw new NullPointerException("Name is null.");
+        }
 
-    hashCode = type.hashCode() * 31 + name.hashCode();
-  }
+        this.type = type;
+        this.name = name;
 
-  Class<T> getType() {
-    return type;
-  }
+        hashCode = type.hashCode() * 31 + name.hashCode();
+    }
 
-  String getName() {
-    return name;
-  }
+    Class<T> getType() {
+        return type;
+    }
 
-  @Override
-  public int hashCode() {
-    return hashCode;
-  }
+    String getName() {
+        return name;
+    }
 
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof Key)) {
-      return false;
+    @Override
+    public int hashCode() {
+        return hashCode;
     }
-    if (o == this) {
-      return true;
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof Key)) {
+            return false;
+        }
+        if (o == this) {
+            return true;
+        }
+        Key other = (Key) o;
+        return name.equals(other.name) && type.equals(other.type);
     }
-    Key other = (Key) o;
-    return name.equals(other.name) && type.equals(other.type);
-  }
 
-  @Override
-  public String toString() {
-    return "[type=" + type.getName() + ", name='" + name + "']";
-  }
+    @Override
+    public String toString() {
+        return "[type=" + type.getName() + ", name='" + name + "']";
+    }
 
-  static <T> Key<T> newInstance(Class<T> type, String name) {
-    return new Key<T>(type, name);
-  }
+    static <T> Key<T> newInstance(Class<T> type, String name) {
+        return new Key<T>(type, name);
+    }
 }

http://git-wip-us.apache.org/repos/asf/struts/blob/2e9df577/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Scope.java
----------------------------------------------------------------------
diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Scope.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Scope.java
index b327db8..62443f7 100644
--- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Scope.java
+++ b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Scope.java
@@ -1,12 +1,12 @@
 /**
  * Copyright (C) 2006 Google Inc.
- *
+ * <p/>
  * Licensed 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
- *
+ * <p/>
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
  * 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.
@@ -25,193 +25,190 @@ import java.util.concurrent.Callable;
  */
 public enum Scope {
 
-  /**
-   * One instance per injection.
-   */
-  DEFAULT {
-    @Override
-            <T> InternalFactory<? extends T> scopeFactory(Class<T> type, String name,
-        InternalFactory<? extends T> factory) {
-      return factory;
-    }
-  },
-
-  /**
-   * One instance per container.
-   */
-  SINGLETON {
-    @Override
-            <T> InternalFactory<? extends T> scopeFactory(Class<T> type, String name,
-        final InternalFactory<? extends T> factory) {
-      return new InternalFactory<T>() {
-        T instance;
-        public T create(InternalContext context) {
-          synchronized (context.getContainer()) {
-            if (instance == null) {
-              instance = factory.create(context);
-            }
-            return instance;
-          }
+    /**
+     * One instance per injection.
+     */
+    DEFAULT {
+        @Override
+        <T> InternalFactory<? extends T> scopeFactory(Class<T> type, String name,
+                                                      InternalFactory<? extends T> factory) {
+            return factory;
         }
+    },
 
+    /**
+     * One instance per container.
+     */
+    SINGLETON {
         @Override
-        public String toString() {
-          return factory.toString();
-        }
-      };
-    }
-  },
-
-  /**
-   * One instance per thread.
-   *
-   * <p><b>Note:</b> if a thread local object strongly references its {@link
-   * Container}, neither the {@code Container} nor the object will be
-   * eligible for garbage collection, i.e. memory leak.
-   */
-  THREAD {
-    @Override
-            <T> InternalFactory<? extends T> scopeFactory(Class<T> type, String name,
-        final InternalFactory<? extends T> factory) {
-      return new InternalFactory<T>() {
-        final ThreadLocal<T> threadLocal = new ThreadLocal<T>();
-        public T create(final InternalContext context) {
-          T t = threadLocal.get();
-          if (t == null) {
-            t = factory.create(context);
-            threadLocal.set(t);
-          }
-          return t;
+        <T> InternalFactory<? extends T> scopeFactory(Class<T> type, String name, final InternalFactory<? extends T> factory) {
+            return new InternalFactory<T>() {
+                T instance;
+
+                public T create(InternalContext context) {
+                    synchronized (context.getContainer()) {
+                        if (instance == null) {
+                            instance = factory.create(context);
+                        }
+                        return instance;
+                    }
+                }
+
+                @Override
+                public String toString() {
+                    return factory.toString();
+                }
+            };
         }
+    },
 
+    /**
+     * One instance per thread.
+     * <p/>
+     * <p><b>Note:</b> if a thread local object strongly references its {@link
+     * Container}, neither the {@code Container} nor the object will be
+     * eligible for garbage collection, i.e. memory leak.
+     */
+    THREAD {
         @Override
-        public String toString() {
-          return factory.toString();
-        }
-      };
-    }
-  },
-
-  /**
-   * One instance per request.
-   */
-  REQUEST {
-    @Override
-            <T> InternalFactory<? extends T> scopeFactory(final Class<T> type,
-        final String name, final InternalFactory<? extends T> factory) {
-      return new InternalFactory<T>() {
-        public T create(InternalContext context) {
-          Strategy strategy = context.getScopeStrategy();
-          try {
-            return strategy.findInRequest(
-                type, name, toCallable(context, factory));
-          } catch (Exception e) {
-            throw new RuntimeException(e);
-          }
+        <T> InternalFactory<? extends T> scopeFactory(Class<T> type, String name, final InternalFactory<? extends T> factory) {
+            return new InternalFactory<T>() {
+                final ThreadLocal<T> threadLocal = new ThreadLocal<T>();
+
+                public T create(final InternalContext context) {
+                    T t = threadLocal.get();
+                    if (t == null) {
+                        t = factory.create(context);
+                        threadLocal.set(t);
+                    }
+                    return t;
+                }
+
+                @Override
+                public String toString() {
+                    return factory.toString();
+                }
+            };
         }
+    },
 
+    /**
+     * One instance per request.
+     */
+    REQUEST {
         @Override
-        public String toString() {
-          return factory.toString();
-        }
-      };
-    }
-  },
-
-  /**
-   * One instance per session.
-   */
-  SESSION {
-    @Override
-            <T> InternalFactory<? extends T> scopeFactory(final Class<T> type,
-        final String name, final InternalFactory<? extends T> factory) {
-      return new InternalFactory<T>() {
-        public T create(InternalContext context) {
-          Strategy strategy = context.getScopeStrategy();
-          try {
-            return strategy.findInSession(
-                type, name, toCallable(context, factory));
-          } catch (Exception e) {
-            throw new RuntimeException(e);
-          }
+        <T> InternalFactory<? extends T> scopeFactory(final Class<T> type, final String name, final InternalFactory<? extends T> factory) {
+            return new InternalFactory<T>() {
+                public T create(InternalContext context) {
+                    Strategy strategy = context.getScopeStrategy();
+                    try {
+                        return strategy.findInRequest(
+                                type, name, toCallable(context, factory));
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+
+                @Override
+                public String toString() {
+                    return factory.toString();
+                }
+            };
         }
+    },
 
+    /**
+     * One instance per session.
+     */
+    SESSION {
         @Override
-        public String toString() {
-          return factory.toString();
-        }
-      };
-    }
-  },
-
-  /**
-   * One instance per wizard.
-   */
-  WIZARD {
-    @Override
-            <T> InternalFactory<? extends T> scopeFactory(final Class<T> type,
-        final String name, final InternalFactory<? extends T> factory) {
-      return new InternalFactory<T>() {
-        public T create(InternalContext context) {
-          Strategy strategy = context.getScopeStrategy();
-          try {
-            return strategy.findInWizard(
-                type, name, toCallable(context, factory));
-          } catch (Exception e) {
-            throw new RuntimeException(e);
-          }
+        <T> InternalFactory<? extends T> scopeFactory(final Class<T> type, final String name, final InternalFactory<? extends T> factory) {
+            return new InternalFactory<T>() {
+                public T create(InternalContext context) {
+                    Strategy strategy = context.getScopeStrategy();
+                    try {
+                        return strategy.findInSession(
+                                type, name, toCallable(context, factory));
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+
+                @Override
+                public String toString() {
+                    return factory.toString();
+                }
+            };
         }
+    },
 
+    /**
+     * One instance per wizard.
+     */
+    WIZARD {
         @Override
-        public String toString() {
-          return factory.toString();
+        <T> InternalFactory<? extends T> scopeFactory(final Class<T> type, final String name, final InternalFactory<? extends T> factory) {
+            return new InternalFactory<T>() {
+                public T create(InternalContext context) {
+                    Strategy strategy = context.getScopeStrategy();
+                    try {
+                        return strategy.findInWizard(
+                                type, name, toCallable(context, factory));
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+
+                @Override
+                public String toString() {
+                    return factory.toString();
+                }
+            };
         }
-      };
-    }
-  };
-
-  <T> Callable<? extends T> toCallable(final InternalContext context,
-      final InternalFactory<? extends T> factory) {
-    return new Callable<T>() {
-      public T call() throws Exception {
-        return factory.create(context);
-      }
     };
-  }
-
-  /**
-   * Wraps factory with scoping logic.
-   */
-  abstract <T> InternalFactory<? extends T> scopeFactory(
-      Class<T> type, String name, InternalFactory<? extends T> factory);
-
-  /**
-   * Pluggable scoping strategy. Enables users to provide custom
-   * implementations of request, session, and wizard scopes. Implement and
-   * pass to {@link
-   * Container#setScopeStrategy(com.opensymphony.xwork2.inject.Scope.Strategy)}.
-   */
-  public interface Strategy {
 
-    /**
-     * Finds an object for the given type and name in the request scope.
-     * Creates a new object if necessary using the given factory.
-     */
-    <T> T findInRequest(Class<T> type, String name,
-        Callable<? extends T> factory) throws Exception;
+    <T> Callable<? extends T> toCallable(final InternalContext context,
+                                         final InternalFactory<? extends T> factory) {
+        return new Callable<T>() {
+            public T call() throws Exception {
+                return factory.create(context);
+            }
+        };
+    }
 
     /**
-     * Finds an object for the given type and name in the session scope.
-     * Creates a new object if necessary using the given factory.
+     * Wraps factory with scoping logic.
      */
-    <T> T findInSession(Class<T> type, String name,
-        Callable<? extends T> factory) throws Exception;
+    abstract <T> InternalFactory<? extends T> scopeFactory(
+            Class<T> type, String name, InternalFactory<? extends T> factory);
 
     /**
-     * Finds an object for the given type and name in the wizard scope.
-     * Creates a new object if necessary using the given factory.
+     * Pluggable scoping strategy. Enables users to provide custom
+     * implementations of request, session, and wizard scopes. Implement and
+     * pass to {@link
+     * Container#setScopeStrategy(com.opensymphony.xwork2.inject.Scope.Strategy)}.
      */
-    <T> T findInWizard(Class<T> type, String name,
-        Callable<? extends T> factory) throws Exception;
-  }
+    public interface Strategy {
+
+        /**
+         * Finds an object for the given type and name in the request scope.
+         * Creates a new object if necessary using the given factory.
+         */
+        <T> T findInRequest(Class<T> type, String name,
+                            Callable<? extends T> factory) throws Exception;
+
+        /**
+         * Finds an object for the given type and name in the session scope.
+         * Creates a new object if necessary using the given factory.
+         */
+        <T> T findInSession(Class<T> type, String name,
+                            Callable<? extends T> factory) throws Exception;
+
+        /**
+         * Finds an object for the given type and name in the wizard scope.
+         * Creates a new object if necessary using the given factory.
+         */
+        <T> T findInWizard(Class<T> type, String name,
+                           Callable<? extends T> factory) throws Exception;
+    }
 }

http://git-wip-us.apache.org/repos/asf/struts/blob/2e9df577/xwork-core/src/main/java/com/opensymphony/xwork2/inject/util/ReferenceCache.java
----------------------------------------------------------------------
diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/util/ReferenceCache.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/util/ReferenceCache.java
index 166742c..9ebf545 100644
--- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/util/ReferenceCache.java
+++ b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/util/ReferenceCache.java
@@ -1,12 +1,12 @@
 /**
  * Copyright (C) 2006 Google Inc.
- *
+ * <p/>
  * Licensed 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
- *
+ * <p/>
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p/>
  * 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.
@@ -16,12 +16,12 @@
 
 package com.opensymphony.xwork2.inject.util;
 
-import static com.opensymphony.xwork2.inject.util.ReferenceType.STRONG;
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.util.concurrent.*;
 
+import static com.opensymphony.xwork2.inject.util.ReferenceType.STRONG;
+
 /**
  * Extends {@link ReferenceMap} to support lazy loading values by overriding
  * {@link #create(Object)}.
@@ -30,155 +30,148 @@ import java.util.concurrent.*;
  */
 public abstract class ReferenceCache<K, V> extends ReferenceMap<K, V> {
 
-  private static final long serialVersionUID = 0;
-
-  transient ConcurrentMap<Object, Future<V>> futures =
-      new ConcurrentHashMap<Object, Future<V>>();
-
-  transient ThreadLocal<Future<V>> localFuture = new ThreadLocal<Future<V>>();
-
-  public ReferenceCache(ReferenceType keyReferenceType,
-      ReferenceType valueReferenceType) {
-    super(keyReferenceType, valueReferenceType);
-  }
-
-  /**
-   * Equivalent to {@code new ReferenceCache(STRONG, STRONG)}.
-   */
-  public ReferenceCache() {
-    super(STRONG, STRONG);
-  }
-
-  /**
-   * Override to lazy load values. Use as an alternative to {@link
-   * #put(Object,Object)}. Invoked by getter if value isn't already cached.
-   * Must not return {@code null}. This method will not be called again until
-   * the garbage collector reclaims the returned value.
-   */
-  protected abstract V create(K key);
-
-  V internalCreate(K key) {
-    try {
-      FutureTask<V> futureTask = new FutureTask<V>(
-          new CallableCreate(key));
-
-      // use a reference so we get the same equality semantics.
-      Object keyReference = referenceKey(key);
-      Future<V> future = futures.putIfAbsent(keyReference, futureTask);
-      if (future == null) {
-        // winning thread.
+    private static final long serialVersionUID = 0;
+
+    transient ConcurrentMap<Object, Future<V>> futures = new ConcurrentHashMap<>();
+    transient ThreadLocal<Future<V>> localFuture = new ThreadLocal<>();
+
+    public ReferenceCache(ReferenceType keyReferenceType, ReferenceType valueReferenceType) {
+        super(keyReferenceType, valueReferenceType);
+    }
+
+    /**
+     * Equivalent to {@code new ReferenceCache(STRONG, STRONG)}.
+     */
+    public ReferenceCache() {
+        super(STRONG, STRONG);
+    }
+
+    /**
+     * Override to lazy load values. Use as an alternative to {@link
+     * #put(Object, Object)}. Invoked by getter if value isn't already cached.
+     * Must not return {@code null}. This method will not be called again until
+     * the garbage collector reclaims the returned value.
+     */
+    protected abstract V create(K key);
+
+    V internalCreate(K key) {
         try {
-          if (localFuture.get() != null) {
-            throw new IllegalStateException(
-                "Nested creations within the same cache are not allowed.");
-          }
-          localFuture.set(futureTask);
-          futureTask.run();
-          V value = futureTask.get();
-          putStrategy().execute(this,
-              keyReference, referenceValue(keyReference, value));
-          return value;
-        } finally {
-          localFuture.remove();
-          futures.remove(keyReference);
+            FutureTask<V> futureTask = new FutureTask<>(new CallableCreate(key));
+
+            // use a reference so we get the same equality semantics.
+            Object keyReference = referenceKey(key);
+            Future<V> future = futures.putIfAbsent(keyReference, futureTask);
+            if (future == null) {
+                // winning thread.
+                try {
+                    if (localFuture.get() != null) {
+                        throw new IllegalStateException("Nested creations within the same cache are not allowed.");
+                    }
+                    localFuture.set(futureTask);
+                    futureTask.run();
+                    V value = futureTask.get();
+                    putStrategy().execute(this, keyReference, referenceValue(keyReference, value));
+                    return value;
+                } finally {
+                    localFuture.remove();
+                    futures.remove(keyReference);
+                }
+            } else {
+                // wait for winning thread.
+                return future.get();
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        } catch (ExecutionException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof RuntimeException) {
+                throw (RuntimeException) cause;
+            } else if (cause instanceof Error) {
+                throw (Error) cause;
+            }
+            throw new RuntimeException(cause);
         }
-      } else {
-        // wait for winning thread.
-        return future.get();
-      }
-    } catch (InterruptedException e) {
-      throw new RuntimeException(e);
-    } catch (ExecutionException e) {
-      Throwable cause = e.getCause();
-      if (cause instanceof RuntimeException) {
-        throw (RuntimeException) cause;
-      } else if (cause instanceof Error) {
-        throw (Error) cause;
-      }
-      throw new RuntimeException(cause);
     }
-  }
-
-  /**
-   * {@inheritDoc}
-   *
-   * If this map does not contain an entry for the given key and {@link
-   * #create(Object)} has been overridden, this method will create a new
-   * value, put it in the map, and return it.
-   *
-   * @throws NullPointerException if {@link #create(Object)} returns null.
-   * @throws java.util.concurrent.CancellationException if the creation is
-   *  cancelled. See {@link #cancel()}.
-   */
-  @SuppressWarnings("unchecked")
-  @Override public V get(final Object key) {
-    V value = super.get(key);
-    return (value == null)
-      ? internalCreate((K) key)
-      : value;
-  }
-
-  /**
-   * Cancels the current {@link #create(Object)}. Throws {@link
-   * java.util.concurrent.CancellationException} to all clients currently
-   * blocked on {@link #get(Object)}.
-   */
-  protected void cancel() {
-    Future<V> future = localFuture.get();
-    if (future == null) {
-      throw new IllegalStateException("Not in create().");
+
+    /**
+     * {@inheritDoc}
+     * <p/>
+     * If this map does not contain an entry for the given key and {@link
+     * #create(Object)} has been overridden, this method will create a new
+     * value, put it in the map, and return it.
+     *
+     * @throws NullPointerException                       if {@link #create(Object)} returns null.
+     * @throws java.util.concurrent.CancellationException if the creation is
+     *                                                    cancelled. See {@link #cancel()}.
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public V get(final Object key) {
+        V value = super.get(key);
+        return (value == null) ? internalCreate((K) key) : value;
+    }
+
+    /**
+     * Cancels the current {@link #create(Object)}. Throws {@link
+     * java.util.concurrent.CancellationException} to all clients currently
+     * blocked on {@link #get(Object)}.
+     */
+    protected void cancel() {
+        Future<V> future = localFuture.get();
+        if (future == null) {
+            throw new IllegalStateException("Not in create().");
+        }
+        future.cancel(false);
     }
-    future.cancel(false);
-  }
 
-  class CallableCreate implements Callable<V> {
+    class CallableCreate implements Callable<V> {
 
-    K key;
+        K key;
+
+        public CallableCreate(K key) {
+            this.key = key;
+        }
+
+        public V call() {
+            // try one more time (a previous future could have come and gone.)
+            V value = internalGet(key);
+            if (value != null) {
+                return value;
+            }
+
+            // create value.
+            value = create(key);
+            if (value == null) {
+                throw new NullPointerException("create(K) returned null for: " + key);
+            }
+            return value;
+        }
+    }
 
-    public CallableCreate(K key) {
-      this.key = key;
+    /**
+     * Returns a {@code ReferenceCache} delegating to the specified {@code
+     * function}. The specified function must not return {@code null}.
+     */
+    public static <K, V> ReferenceCache<K, V> of(
+            ReferenceType keyReferenceType,
+            ReferenceType valueReferenceType,
+            final Function<? super K, ? extends V> function) {
+        ensureNotNull(function);
+        return new ReferenceCache<K, V>(keyReferenceType, valueReferenceType) {
+            @Override
+            protected V create(K key) {
+                return function.apply(key);
+            }
+
+            private static final long serialVersionUID = 0;
+        };
     }
 
-    public V call() {
-      // try one more time (a previous future could have come and gone.)
-      V value = internalGet(key);
-      if (value != null) {
-        return value;
-      }
-
-      // create value.
-      value = create(key);
-      if (value == null) {
-        throw new NullPointerException(
-            "create(K) returned null for: " + key);
-      }
-      return value;
+    private void readObject(ObjectInputStream in) throws IOException,
+            ClassNotFoundException {
+        in.defaultReadObject();
+        this.futures = new ConcurrentHashMap<>();
+        this.localFuture = new ThreadLocal<>();
     }
-  }
-
-  /**
-   * Returns a {@code ReferenceCache} delegating to the specified {@code
-   * function}. The specified function must not return {@code null}.
-   */
-  public static <K, V> ReferenceCache<K, V> of(
-      ReferenceType keyReferenceType,
-      ReferenceType valueReferenceType,
-      final Function<? super K, ? extends V> function) {
-    ensureNotNull(function);
-    return new ReferenceCache<K, V>(keyReferenceType, valueReferenceType) {
-      @Override
-      protected V create(K key) {
-        return function.apply(key);
-      }
-      private static final long serialVersionUID = 0;
-    };
-  }
-
-  private void readObject(ObjectInputStream in) throws IOException,
-      ClassNotFoundException {
-    in.defaultReadObject();
-    this.futures = new ConcurrentHashMap<Object, Future<V>>();
-    this.localFuture = new ThreadLocal<Future<V>>();
-  }
 
 }


Mime
View raw message