http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultActionFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultActionFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultActionFactory.java deleted file mode 100644 index a17484a..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultActionFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.inject.Inject; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultActionFactory implements ActionFactory { - - private ObjectFactory objectFactory; - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - public Object buildAction(String actionName, String namespace, ActionConfig config, Map<String, Object> extraContext) throws Exception { - return objectFactory.buildBean(config.getClassName(), extraContext); - } - -}
http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultConverterFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultConverterFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultConverterFactory.java deleted file mode 100644 index e35222e..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultConverterFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultConverterFactory implements ConverterFactory { - - private static final Logger LOG = LogManager.getLogger(DefaultConverterFactory.class); - - private Container container; - - @Inject - public void setContainer(Container container) { - this.container = container; - } - - public TypeConverter buildConverter(Class<? extends TypeConverter> converterClass, Map<String, Object> extraContext) throws Exception { - LOG.debug("Creating converter of type [{}]", converterClass.getCanonicalName()); - return container.getInstance(converterClass); - } - -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java deleted file mode 100644 index 9f0195f..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.entities.InterceptorConfig; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.interceptor.Interceptor; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; - -import java.util.HashMap; -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultInterceptorFactory implements InterceptorFactory { - - private ObjectFactory objectFactory; - private ReflectionProvider reflectionProvider; - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - @Inject - public void setReflectionProvider(ReflectionProvider reflectionProvider) { - this.reflectionProvider = reflectionProvider; - } - - public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map<String, String> interceptorRefParams) throws ConfigurationException { - String interceptorClassName = interceptorConfig.getClassName(); - Map<String, String> thisInterceptorClassParams = interceptorConfig.getParams(); - Map<String, String> params = (thisInterceptorClassParams == null) ? new HashMap<String, String>() : new HashMap<>(thisInterceptorClassParams); - params.putAll(interceptorRefParams); - - String message; - Throwable cause; - - try { - // interceptor instances are long-lived and used across user sessions, so don't try to pass in any extra context - Interceptor interceptor = (Interceptor) objectFactory.buildBean(interceptorClassName, null); - reflectionProvider.setProperties(params, interceptor); - interceptor.init(); - - return interceptor; - } catch (InstantiationException e) { - cause = e; - message = "Unable to instantiate an instance of Interceptor class [" + interceptorClassName + "]."; - } catch (IllegalAccessException e) { - cause = e; - message = "IllegalAccessException while attempting to instantiate an instance of Interceptor class [" + interceptorClassName + "]."; - } catch (ClassCastException e) { - cause = e; - message = "Class [" + interceptorClassName + "] does not implement com.opensymphony.xwork2.interceptor.Interceptor"; - } catch (Exception e) { - cause = e; - message = "Caught Exception while registering Interceptor class " + interceptorClassName; - } catch (NoClassDefFoundError e) { - cause = e; - message = "Could not load class " + interceptorClassName + ". Perhaps it exists but certain dependencies are not available?"; - } - - throw new ConfigurationException(message, cause, interceptorConfig); - } - -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultResultFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultResultFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultResultFactory.java deleted file mode 100644 index a5a6c79..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultResultFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.Result; -import com.opensymphony.xwork2.config.entities.ResultConfig; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.reflection.ReflectionException; -import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultResultFactory implements ResultFactory { - - private ObjectFactory objectFactory; - private ReflectionProvider reflectionProvider; - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - @Inject - public void setReflectionProvider(ReflectionProvider reflectionProvider) { - this.reflectionProvider = reflectionProvider; - } - - public Result buildResult(ResultConfig resultConfig, Map<String, Object> extraContext) throws Exception { - String resultClassName = resultConfig.getClassName(); - Result result = null; - - if (resultClassName != null) { - result = (Result) objectFactory.buildBean(resultClassName, extraContext); - Map<String, String> params = resultConfig.getParams(); - if (params != null) { - for (Map.Entry<String, String> paramEntry : params.entrySet()) { - try { - reflectionProvider.setProperty(paramEntry.getKey(), paramEntry.getValue(), result, extraContext, true); - } catch (ReflectionException ex) { - if (result instanceof ReflectionExceptionHandler) { - ((ReflectionExceptionHandler) result).handle(ex); - } - } - } - } - } - - return result; - } - -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultUnknownHandlerFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultUnknownHandlerFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultUnknownHandlerFactory.java deleted file mode 100644 index 58fb339..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultUnknownHandlerFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.UnknownHandler; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultUnknownHandlerFactory implements UnknownHandlerFactory { - - private Container container; - - @Inject - public void setContainer(Container container) { - this.container = container; - } - - public UnknownHandler buildUnknownHandler(String unknownHandlerName, Map<String, Object> extraContext) throws Exception { - return container.getInstance(UnknownHandler.class, unknownHandlerName); - } - -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultValidatorFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultValidatorFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultValidatorFactory.java deleted file mode 100644 index 8ce8b77..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/DefaultValidatorFactory.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; -import com.opensymphony.xwork2.validator.Validator; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultValidatorFactory implements ValidatorFactory { - - private ObjectFactory objectFactory; - private ReflectionProvider reflectionProvider; - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - @Inject - public void setReflectionProvider(ReflectionProvider reflectionProvider) { - this.reflectionProvider = reflectionProvider; - } - - public Validator buildValidator(String className, Map<String, Object> params, Map<String, Object> extraContext) throws Exception { - Validator validator = (Validator) objectFactory.buildBean(className, extraContext); - reflectionProvider.setProperties(params, validator, extraContext); - - return validator; - } -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/InterceptorFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/InterceptorFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/InterceptorFactory.java deleted file mode 100644 index 742e7ab..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/InterceptorFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.entities.InterceptorConfig; -import com.opensymphony.xwork2.interceptor.Interceptor; - -import java.util.Map; - -/** - * Dedicated interface used by {@link com.opensymphony.xwork2.ObjectFactory} to build {@link com.opensymphony.xwork2.interceptor.Interceptor} - */ -public interface InterceptorFactory { - - /** - * Builds an Interceptor from the InterceptorConfig and the Map of - * parameters from the interceptor reference. Implementations of this method - * should ensure that the Interceptor is parameterized with both the - * parameters from the Interceptor config and the interceptor ref Map (the - * interceptor ref params take precedence), and that the Interceptor.init() - * method is called on the Interceptor instance before it is returned. - * - * @param interceptorConfig the InterceptorConfig from the configuration - * @param interceptorRefParams a Map of params provided in the Interceptor reference in the - * Action mapping or InterceptorStack definition - */ - Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map<String, String> interceptorRefParams) throws ConfigurationException; - -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/ResultFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/ResultFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/ResultFactory.java deleted file mode 100644 index c7191cb..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/ResultFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.Result; -import com.opensymphony.xwork2.config.entities.ResultConfig; - -import java.util.Map; - -/** - * Used by {@link com.opensymphony.xwork2.ObjectFactory} to build {@link com.opensymphony.xwork2.Result} - */ -public interface ResultFactory { - - Result buildResult(ResultConfig resultConfig, Map<String, Object> extraContext) throws Exception; - -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/UnknownHandlerFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/UnknownHandlerFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/UnknownHandlerFactory.java deleted file mode 100644 index 244f3ab..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/UnknownHandlerFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.UnknownHandler; - -import java.util.Map; - -/** - * Dedicated interface used by {@link com.opensymphony.xwork2.ObjectFactory} to build {@link com.opensymphony.xwork2.UnknownHandler} - */ -public interface UnknownHandlerFactory { - - /** - * Builds unknown handler of given name - * - * @param unknownHandlerName name of unknown handler defined in struts.xml - * @param extraContext extra params - * @return instance of {@link com.opensymphony.xwork2.UnknownHandler} with injected dependencies - */ - UnknownHandler buildUnknownHandler(String unknownHandlerName, Map<String, Object> extraContext) throws Exception; - -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/factory/ValidatorFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/ValidatorFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/factory/ValidatorFactory.java deleted file mode 100644 index bbaa36e..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/factory/ValidatorFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.validator.Validator; - -import java.util.Map; - -/** - * Dedicated interface used by {@link com.opensymphony.xwork2.ObjectFactory} to build {@link Validator} - */ -public interface ValidatorFactory { - - /** - * Build a Validator of the given type and set the parameters on it - * - * @param className the type of Validator to build - * @param params property name -> value Map to set onto the Validator instance - * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext} - */ - Validator buildValidator(String className, Map<String, Object> params, Map<String, Object> extraContext) throws Exception; - -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ConstructionContext.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ConstructionContext.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ConstructionContext.java deleted file mode 100644 index d75d464..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ConstructionContext.java +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.List; - -/** - * Context of a dependency construction. Used to manage circular references. - * - * @author [email protected] (Bob Lee) - */ -class ConstructionContext<T> { - - T currentReference; - boolean constructing; - - List<DelegatingInvocationHandler<T>> invocationHandlers; - - T getCurrentReference() { - return currentReference; - } - - void removeCurrentReference() { - this.currentReference = null; - } - - void setCurrentReference(T currentReference) { - this.currentReference = currentReference; - } - - boolean isConstructing() { - return constructing; - } - - void startConstruction() { - this.constructing = true; - } - - void finishConstruction() { - this.constructing = false; - invocationHandlers = null; - } - - Object createProxy(Class<? super T> expectedType) { - // TODO: if I create a proxy which implements all the interfaces of - // the implementation type, I'll be able to get away with one proxy - // instance (as opposed to one per caller). - - if (!expectedType.isInterface()) { - throw new DependencyException(expectedType.getName() + " is not an interface."); - } - - if (invocationHandlers == null) { - invocationHandlers = new ArrayList<DelegatingInvocationHandler<T>>(); - } - - DelegatingInvocationHandler<T> invocationHandler = new DelegatingInvocationHandler<>(); - invocationHandlers.add(invocationHandler); - - return Proxy.newProxyInstance( - expectedType.getClassLoader(), - new Class[] { expectedType }, - invocationHandler - ); - } - - void setProxyDelegates(T delegate) { - if (invocationHandlers != null) { - for (DelegatingInvocationHandler<T> invocationHandler : invocationHandlers) { - invocationHandler.setDelegate(delegate); - } - } - } - - static class DelegatingInvocationHandler<T> implements InvocationHandler { - - T delegate; - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - if (delegate == null) { - throw new IllegalStateException( - "Not finished constructing. Please don't call methods on this" - + " object until the caller's construction is complete."); - } - - try { - return method.invoke(delegate, args); - } catch (IllegalAccessException | IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } - } - - void setDelegate(T delegate) { - this.delegate = delegate; - } - } -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Container.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Container.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Container.java deleted file mode 100644 index bca6032..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Container.java +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -import java.io.Serializable; -import java.util.Set; - -/** - * Injects dependencies into constructors, methods and fields annotated with - * {@link Inject}. Immutable. - * - * <p>When injecting a method or constructor, you can additionally annotate - * its parameters with {@link Inject} and specify a dependency name. When a - * parameter has no annotation, the container uses the name from the method or - * constructor's {@link Inject} annotation respectively. - * - * <p>For example: - * - * <pre> - * class Foo { - * - * // Inject the int constant named "i". - * @Inject("i") int i; - * - * // Inject the default implementation of Bar and the String constant - * // named "s". - * @Inject Foo(Bar bar, @Inject("s") String s) { - * ... - * } - * - * // Inject the default implementation of Baz and the Bob implementation - * // named "foo". - * @Inject void initialize(Baz baz, @Inject("foo") Bob bob) { - * ... - * } - * - * // Inject the default implementation of Tee. - * @Inject void setTee(Tee tee) { - * ... - * } - * } - * </pre> - * - * <p>To create and inject an instance of {@code Foo}: - * - * <pre> - * Container c = ...; - * Foo foo = c.inject(Foo.class); - * </pre> - * - * @see ContainerBuilder - * @author [email protected] (Bob Lee) - */ -public interface Container extends Serializable { - - /** - * Default dependency name. - */ - String DEFAULT_NAME = "default"; - - /** - * Injects dependencies into the fields and methods of an existing object. - */ - void inject(Object o); - - /** - * Creates and injects a new instance of type {@code implementation}. - */ - <T> T inject(Class<T> implementation); - - /** - * Gets an instance of the given dependency which was declared in - * {@link com.opensymphony.xwork2.inject.ContainerBuilder}. - */ - <T> T getInstance(Class<T> type, String name); - - /** - * Convenience method. Equivalent to {@code getInstance(type, - * DEFAULT_NAME)}. - */ - <T> T getInstance(Class<T> type); - - /** - * Gets a set of all registered names for the given type - * @param type The instance type - * @return A set of registered names or empty set if no instances are registered for that type - */ - Set<String> getInstanceNames(Class<?> type); - - /** - * Sets the scope strategy for the current thread. - */ - void setScopeStrategy(Scope.Strategy scopeStrategy); - - /** - * Removes the scope strategy for the current thread. - */ - void removeScopeStrategy(); -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerBuilder.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerBuilder.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerBuilder.java deleted file mode 100644 index 54f5be6..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerBuilder.java +++ /dev/null @@ -1,510 +0,0 @@ -/** - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -import java.lang.reflect.Member; -import java.util.*; -import java.util.logging.Logger; - -/** - * Builds a dependency injection {@link Container}. The combination of - * dependency type and name uniquely identifies a dependency mapping; you can - * use the same name for two different types. Not safe for concurrent use. - * - * <p>Adds the following factories by default: - * - * <ul> - * <li>Injects the current {@link Container}. - * <li>Injects the {@link Logger} for the injected member's declaring class. - * </ul> - * - * @author [email protected] (Bob Lee) - */ -public final class ContainerBuilder { - - final Map<Key<?>, InternalFactory<?>> factories = new HashMap<>(); - final List<InternalFactory<?>> singletonFactories = new ArrayList<>(); - final List<Class<?>> staticInjections = new ArrayList<>(); - boolean created; - boolean allowDuplicates = false; - - private static final InternalFactory<Container> CONTAINER_FACTORY = - new InternalFactory<Container>() { - public Container create(InternalContext context) { - return context.getContainer(); - } - }; - - private static final InternalFactory<Logger> LOGGER_FACTORY = - new InternalFactory<Logger>() { - public Logger create(InternalContext context) { - Member member = context.getExternalContext().getMember(); - return member == null ? Logger.getAnonymousLogger() - : Logger.getLogger(member.getDeclaringClass().getName()); - } - }; - - /** - * Constructs a new builder. - */ - public ContainerBuilder() { - // In the current container as the default Container implementation. - factories.put(Key.newInstance(Container.class, Container.DEFAULT_NAME), CONTAINER_FACTORY); - - // Inject the logger for the injected member's declaring class. - factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY); - } - - /** - * Maps a dependency. All methods in this class ultimately funnel through - * here. - */ - private <T> ContainerBuilder factory(final Key<T> key, - InternalFactory<? extends T> factory, Scope scope) { - ensureNotCreated(); - checkKey(key); - final InternalFactory<? extends T> scopedFactory = scope.scopeFactory(key.getType(), key.getName(), factory); - factories.put(key, scopedFactory); - if (scope == Scope.SINGLETON) { - singletonFactories.add(new InternalFactory<T>() { - public T create(InternalContext context) { - try { - context.setExternalContext(ExternalContext.newInstance(null, key, context.getContainerImpl())); - return scopedFactory.create(context); - } finally { - context.setExternalContext(null); - } - } - }); - } - return this; - } - - /** - * Ensures a key isn't already mapped. - */ - private void checkKey(Key<?> key) { - if (factories.containsKey(key) && !allowDuplicates) { - throw new DependencyException("Dependency mapping for " + key + " already exists."); - } - } - - /** - * Maps a factory to a given dependency type and name. - * - * @param type of dependency - * @param name of dependency - * @param factory creates objects to inject - * @param scope scope of injected instances - * @return this builder - */ - public <T> ContainerBuilder factory(final Class<T> type, final String name, - final Factory<? extends T> factory, Scope scope) { - InternalFactory<T> internalFactory = new InternalFactory<T>() { - - public T create(InternalContext context) { - try { - Context externalContext = context.getExternalContext(); - return factory.create(externalContext); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public String toString() { - return new LinkedHashMap<String, Object>() {{ - put("type", type); - put("name", name); - put("factory", factory); - }}.toString(); - } - }; - - return factory(Key.newInstance(type, name), internalFactory, scope); - } - - /** - * Convenience method. Equivalent to {@code factory(type, - * Container.DEFAULT_NAME, factory, scope)}. - * - * @see #factory(Class, String, Factory, Scope) - */ - public <T> ContainerBuilder factory(Class<T> type, Factory<? extends T> factory, Scope scope) { - return factory(type, Container.DEFAULT_NAME, factory, scope); - } - - /** - * Convenience method. Equivalent to {@code factory(type, name, factory, - * Scope.DEFAULT)}. - * - * @see #factory(Class, String, Factory, Scope) - */ - public <T> ContainerBuilder factory(Class<T> type, String name, Factory<? extends T> factory) { - return factory(type, name, factory, Scope.DEFAULT); - } - - /** - * Convenience method. Equivalent to {@code factory(type, - * Container.DEFAULT_NAME, factory, Scope.DEFAULT)}. - * - * @see #factory(Class, String, Factory, Scope) - */ - public <T> ContainerBuilder factory(Class<T> type, Factory<? extends T> factory) { - return factory(type, Container.DEFAULT_NAME, factory, Scope.DEFAULT); - } - - /** - * Maps an implementation class to a given dependency type and name. Creates - * instances using the container, recursively injecting dependencies. - * - * @param type of dependency - * @param name of dependency - * @param implementation class - * @param scope scope of injected instances - * @return this builder - */ - public <T> ContainerBuilder factory(final Class<T> type, final String name, - final Class<? extends T> implementation, final Scope scope) { - // This factory creates new instances of the given implementation. - // We have to lazy load the constructor because the Container - // hasn't been created yet. - InternalFactory<? extends T> factory = new InternalFactory<T>() { - - volatile ContainerImpl.ConstructorInjector<? extends T> constructor; - - @SuppressWarnings("unchecked") - public T create(InternalContext context) { - if (constructor == null) { - this.constructor = - context.getContainerImpl().getConstructor(implementation); - } - return (T) constructor.construct(context, type); - } - - @Override - public String toString() { - return new LinkedHashMap<String, Object>() {{ - put("type", type); - put("name", name); - put("implementation", implementation); - put("scope", scope); - }}.toString(); - } - }; - - return factory(Key.newInstance(type, name), factory, scope); - } - - /** - * Maps an implementation class to a given dependency type and name. Creates - * instances using the container, recursively injecting dependencies. - * <p/> - * <p>Sets scope to value from {@link Scoped} annotation on the - * implementation class. Defaults to {@link Scope#DEFAULT} if no annotation - * is found. - * - * @param type of dependency - * @param name of dependency - * @param implementation class - * @return this builder - */ - public <T> ContainerBuilder factory(final Class<T> type, String name, - final Class<? extends T> implementation) { - Scoped scoped = implementation.getAnnotation(Scoped.class); - Scope scope = scoped == null ? Scope.DEFAULT : scoped.value(); - return factory(type, name, implementation, scope); - } - - /** - * Convenience method. Equivalent to {@code factory(type, - * Container.DEFAULT_NAME, implementation)}. - * - * @see #factory(Class, String, Class) - */ - public <T> ContainerBuilder factory(Class<T> type, Class<? extends T> implementation) { - return factory(type, Container.DEFAULT_NAME, implementation); - } - - /** - * Convenience method. Equivalent to {@code factory(type, - * Container.DEFAULT_NAME, type)}. - * - * @see #factory(Class, String, Class) - */ - public <T> ContainerBuilder factory(Class<T> type) { - return factory(type, Container.DEFAULT_NAME, type); - } - - /** - * Convenience method. Equivalent to {@code factory(type, name, type)}. - * - * @see #factory(Class, String, Class) - */ - public <T> ContainerBuilder factory(Class<T> type, String name) { - return factory(type, name, type); - } - - /** - * Convenience method. Equivalent to {@code factory(type, - * Container.DEFAULT_NAME, implementation, scope)}. - * - * @see #factory(Class, String, Class, Scope) - */ - public <T> ContainerBuilder factory(Class<T> type, Class<? extends T> implementation, Scope scope) { - return factory(type, Container.DEFAULT_NAME, implementation, scope); - } - - /** - * Convenience method. Equivalent to {@code factory(type, - * Container.DEFAULT_NAME, type, scope)}. - * - * @see #factory(Class, String, Class, Scope) - */ - public <T> ContainerBuilder factory(Class<T> type, Scope scope) { - return factory(type, Container.DEFAULT_NAME, type, scope); - } - - /** - * Convenience method. Equivalent to {@code factory(type, name, type, - * scope)}. - * - * @see #factory(Class, String, Class, Scope) - */ - public <T> ContainerBuilder factory(Class<T> type, String name, Scope scope) { - return factory(type, name, type, scope); - } - - /** - * Convenience method. Equivalent to {@code alias(type, Container.DEFAULT_NAME, - * type)}. - * - * @see #alias(Class, String, String) - */ - public <T> ContainerBuilder alias(Class<T> type, String alias) { - return alias(type, Container.DEFAULT_NAME, alias); - } - - /** - * Maps an existing factory to a new name. - * - * @param type of dependency - * @param name of dependency - * @param alias of to the dependency - * @return this builder - */ - public <T> ContainerBuilder alias(Class<T> type, String name, String alias) { - return alias(Key.newInstance(type, name), Key.newInstance(type, alias)); - } - - /** - * Maps an existing dependency. All methods in this class ultimately funnel through - * here. - */ - private <T> ContainerBuilder alias(final Key<T> key, - final Key<T> aliasKey) { - ensureNotCreated(); - checkKey(aliasKey); - - final InternalFactory<? extends T> scopedFactory = (InternalFactory<? extends T>) factories.get(key); - if (scopedFactory == null) { - throw new DependencyException("Dependency mapping for " + key + " doesn't exists."); - } - factories.put(aliasKey, scopedFactory); - return this; - } - - /** - * Maps a constant value to the given name. - */ - public ContainerBuilder constant(String name, String value) { - return constant(String.class, name, value); - } - - /** - * Maps a constant value to the given name. - */ - public ContainerBuilder constant(String name, int value) { - return constant(int.class, name, value); - } - - /** - * Maps a constant value to the given name. - */ - public ContainerBuilder constant(String name, long value) { - return constant(long.class, name, value); - } - - /** - * Maps a constant value to the given name. - */ - public ContainerBuilder constant(String name, boolean value) { - return constant(boolean.class, name, value); - } - - /** - * Maps a constant value to the given name. - */ - public ContainerBuilder constant(String name, double value) { - return constant(double.class, name, value); - } - - /** - * Maps a constant value to the given name. - */ - public ContainerBuilder constant(String name, float value) { - return constant(float.class, name, value); - } - - /** - * Maps a constant value to the given name. - */ - public ContainerBuilder constant(String name, short value) { - return constant(short.class, name, value); - } - - /** - * Maps a constant value to the given name. - */ - public ContainerBuilder constant(String name, char value) { - return constant(char.class, name, value); - } - - /** - * Maps a class to the given name. - */ - public ContainerBuilder constant(String name, Class value) { - return constant(Class.class, name, value); - } - - /** - * Maps an enum to the given name. - */ - public <E extends Enum<E>> ContainerBuilder constant(String name, E value) { - return constant(value.getDeclaringClass(), name, value); - } - - /** - * Maps a constant value to the given type and name. - */ - private <T> ContainerBuilder constant(final Class<T> type, final String name, final T value) { - InternalFactory<T> factory = new InternalFactory<T>() { - public T create(InternalContext ignored) { - return value; - } - - @Override - public String toString() { - return new LinkedHashMap<String, Object>() { - { - put("type", type); - put("name", name); - put("value", value); - } - }.toString(); - } - }; - - return factory(Key.newInstance(type, name), factory, Scope.DEFAULT); - } - - /** - * Upon creation, the {@link Container} will inject static fields and methods - * into the given classes. - * - * @param types for which static members will be injected - */ - public ContainerBuilder injectStatics(Class<?>... types) { - staticInjections.addAll(Arrays.asList(types)); - return this; - } - - /** - * Returns true if this builder contains a mapping for the given type and - * name. - */ - public boolean contains(Class<?> type, String name) { - return factories.containsKey(Key.newInstance(type, name)); - } - - /** - * Convenience method. Equivalent to {@code contains(type, - * Container.DEFAULT_NAME)}. - */ - public boolean contains(Class<?> type) { - return contains(type, Container.DEFAULT_NAME); - } - - /** - * Creates a {@link Container} instance. Injects static members for classes - * which were registered using {@link #injectStatics(Class...)}. - * - * @param loadSingletons If true, the container will load all singletons - * now. If false, the container will lazily load singletons. Eager loading - * is appropriate for production use while lazy loading can speed - * development. - * @throws IllegalStateException if called more than once - */ - public Container create(boolean loadSingletons) { - ensureNotCreated(); - created = true; - final ContainerImpl container = new ContainerImpl(new HashMap<>(factories)); - if (loadSingletons) { - container.callInContext(new ContainerImpl.ContextualCallable<Void>() { - public Void call(InternalContext context) { - for (InternalFactory<?> factory : singletonFactories) { - factory.create(context); - } - return null; - } - }); - } - container.injectStatics(staticInjections); - return container; - } - - /** - * Currently we only support creating one Container instance per builder. - * If we want to support creating more than one container per builder, - * we should move to a "factory factory" model where we create a factory - * instance per Container. Right now, one factory instance would be - * shared across all the containers, singletons synchronize on the - * container when lazy loading, etc. - */ - private void ensureNotCreated() { - if (created) { - throw new IllegalStateException("Container already created."); - } - } - - public void setAllowDuplicates(boolean val) { - allowDuplicates = val; - } - - /** - * Implemented by classes which participate in building a container. - */ - public interface Command { - - /** - * Contributes factories to the given builder. - * - * @param builder - */ - void build(ContainerBuilder builder); - } -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/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 deleted file mode 100644 index 1879933..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java +++ /dev/null @@ -1,603 +0,0 @@ -/** - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -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; - -/** - * Default {@link Container} implementation. - * - * @author [email protected] (Bob Lee) - * @see ContainerBuilder - */ -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<>(); - 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<>(); - - 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/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Context.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Context.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Context.java deleted file mode 100644 index 233b5e4..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Context.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -import java.lang.reflect.Member; - -/** - * Context of the current injection. - * - * @author [email protected] (Bob Lee) - */ -public interface Context { - - /** - * Gets the {@link Container}. - */ - Container getContainer(); - - /** - * Gets the current scope strategy. See {@link - * Container#setScopeStrategy(Scope.Strategy)}. - * - * @throws IllegalStateException if no strategy has been set - */ - Scope.Strategy getScopeStrategy(); - - /** - * Gets the field, method or constructor which is being injected. Returns - * {@code null} if the object currently being constructed is pre-loaded as - * a singleton or requested from {@link Container#getInstance(Class)}. - */ - Member getMember(); - - /** - * Gets the type of the field or parameter which is being injected. - */ - Class<?> getType(); - - /** - * Gets the name of the injection specified by {@link Inject#value()}. - */ - String getName(); -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/inject/DependencyException.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/DependencyException.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/DependencyException.java deleted file mode 100644 index f92896d..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/DependencyException.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -/** - * Thrown when a dependency is misconfigured. - * - * @author [email protected] (Bob Lee) - */ -public class DependencyException extends RuntimeException { - - public DependencyException(String message) { - super(message); - } - - public DependencyException(String message, Throwable cause) { - super(message, cause); - } - - public DependencyException(Throwable cause) { - super(cause); - } -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/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 deleted file mode 100644 index 0c054e8..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/ExternalContext.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -import java.lang.reflect.Member; -import java.util.LinkedHashMap; - -/** - * An immutable snapshot of the current context which is safe to - * expose to client code. - * - * @author [email protected] (Bob Lee) - */ -class ExternalContext<T> implements Context { - - 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 Class<T> getType() { - return key.getType(); - } - - public Scope.Strategy getScopeStrategy() { - return (Scope.Strategy) container.localScopeStrategy.get(); - } - - public Container getContainer() { - return container; - } - - public Member getMember() { - return member; - } - - 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(); - } - - 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/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Factory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Factory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Factory.java deleted file mode 100644 index 1117506..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Factory.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -/** - * A custom factory. Creates objects which will be injected. - * - * @author [email protected] (Bob Lee) - */ -public interface Factory<T> { - - /** - * Creates an object to be injected. - * - * @param context of this injection - * @return instance to be injected - * @throws Exception if unable to create object - */ - T create(Context context) throws Exception; -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Inject.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Inject.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Inject.java deleted file mode 100644 index 610d2bb..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Inject.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -import static com.opensymphony.xwork2.inject.Container.DEFAULT_NAME; - -import static java.lang.annotation.ElementType.*; -import java.lang.annotation.Retention; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Target; - -/** - * <p>Annotates members and parameters which should have their value[s] - * injected. - * - * @author [email protected] (Bob Lee) - */ -@Target({METHOD, CONSTRUCTOR, FIELD, PARAMETER}) -@Retention(RUNTIME) -public @interface Inject { - - /** - * Dependency name. Defaults to {@link Container#DEFAULT_NAME}. - */ - String value() default DEFAULT_NAME; - - /** - * Whether or not injection is required. Applicable only to methods and - * fields (not constructors or parameters). - */ - boolean required() default true; -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/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 deleted file mode 100644 index 7014480..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalContext.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -import java.util.HashMap; -import java.util.Map; - -/** - * Internal context. Used to coordinate injections and support circular - * dependencies. - * - * @author [email protected] (Bob Lee) - */ -class InternalContext { - - final ContainerImpl container; - final Map<Object, ConstructionContext<?>> constructionContexts = new HashMap<Object, ConstructionContext<?>>(); - Scope.Strategy scopeStrategy; - ExternalContext<?> externalContext; - - InternalContext(ContainerImpl container) { - this.container = container; - } - - public Container getContainer() { - return container; - } - - ContainerImpl getContainerImpl() { - return container; - } - - Scope.Strategy getScopeStrategy() { - if (scopeStrategy == null) { - scopeStrategy = (Scope.Strategy) container.localScopeStrategy.get(); - - if (scopeStrategy == null) { - throw new IllegalStateException("Scope strategy not set. Please call Container.setScopeStrategy()."); - } - } - - return scopeStrategy; - } - - @SuppressWarnings("unchecked") - <T> ConstructionContext<T> getConstructionContext(Object key) { - ConstructionContext<T> constructionContext = (ConstructionContext<T>) constructionContexts.get(key); - if (constructionContext == null) { - constructionContext = new ConstructionContext<T>(); - constructionContexts.put(key, constructionContext); - } - return constructionContext; - } - - @SuppressWarnings("unchecked") - <T> ExternalContext<T> getExternalContext() { - return (ExternalContext<T>) externalContext; - } - - void setExternalContext(ExternalContext<?> externalContext) { - this.externalContext = externalContext; - } -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java ---------------------------------------------------------------------- diff --git a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java b/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java deleted file mode 100644 index 49fcf27..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -import java.io.Serializable; - -/** - * Creates objects which will be injected. - * - * @author [email protected] (Bob Lee) - */ -interface InternalFactory<T> extends Serializable { - - /** - * Creates an object to be injected. - * - * @param context of this injection - * @return instance to be injected - */ - T create(InternalContext context); -} http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/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 deleted file mode 100644 index ad9e0ba..0000000 --- a/xwork-core/src/main/java/com/opensymphony/xwork2/inject/Key.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.opensymphony.xwork2.inject; - -/** - * Dependency mapping key. Uniquely identified by the required type and name. - * - * @author [email protected] (Bob Lee) - */ -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."); - } - - this.type = type; - this.name = name; - - hashCode = type.hashCode() * 31 + name.hashCode(); - } - - Class<T> getType() { - return type; - } - - String getName() { - return name; - } - - @Override - public int hashCode() { - return hashCode; - } - - @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); - } - - @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); - } -}
