001: /*****************************************************************************
002: * Copyright (c) PicoContainer Organization. All rights reserved. *
003: * ------------------------------------------------------------------------- *
004: * The software in this package is published under the terms of the BSD *
005: * style license a copy of which has been included with this distribution in *
006: * the LICENSE.txt file. *
007: * *
008: * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant *
009: *****************************************************************************/package org.picocontainer.injectors;
010:
011: import java.io.Serializable;
012: import java.lang.reflect.AccessibleObject;
013: import java.util.Properties;
014:
015: import org.picocontainer.Characteristics;
016: import org.picocontainer.ComponentAdapter;
017: import org.picocontainer.ComponentMonitor;
018: import org.picocontainer.InjectionFactory;
019: import org.picocontainer.LifecycleStrategy;
020: import org.picocontainer.Parameter;
021: import org.picocontainer.PicoCompositionException;
022: import org.picocontainer.annotations.Inject;
023: import org.picocontainer.behaviors.AbstractBehaviorFactory;
024:
025: /**
026: * Creates injector instances, depending on the injection characteristics of the component class.
027: * It will attempt to create a component adapter with - in order of priority:
028: * <ol>
029: * <li>Annotated field injection: if annotation {@link @Inject} is found for field</li>
030: * <li>Annotated method injection: if annotation {@link @Inject} is found for method</li>
031: * <li>Setter injection: if {@link Characteristics.SDI} is found</li>
032: * <li>Method injection: if {@link Characteristics.METHOD_INJECTION} if found</li>
033: * <li>Constructor injection (the default, must find {@link Characteristics.CDI})</li>
034: * </ol>
035: *
036: * @author Paul Hammant
037: * @author Mauro Talevi
038: * @see AnnotatedFieldInjection
039: * @see AnnotatedMethodInjection
040: * @see SetterInjection
041: * @see MethodInjection
042: * @see ConstructorInjection
043: */
044: public class AdaptingInjection implements InjectionFactory,
045: Serializable {
046:
047: /**
048: * Serialization UUID.
049: */
050: private static final long serialVersionUID = 8660775238892763896L;
051:
052: public <T> ComponentAdapter<T> createComponentAdapter(
053: ComponentMonitor componentMonitor,
054: LifecycleStrategy lifecycleStrategy,
055: Properties componentProperties, Object componentKey,
056: Class<T> componentImplementation, Parameter... parameters)
057: throws PicoCompositionException {
058: ComponentAdapter<T> componentAdapter = null;
059:
060: componentAdapter = fieldAnnotatedInjectionAdapter(
061: componentImplementation, componentMonitor,
062: lifecycleStrategy, componentProperties, componentKey,
063: componentAdapter, parameters);
064:
065: if (componentAdapter != null) {
066: return componentAdapter;
067: }
068:
069: componentAdapter = methodAnnotatedInjectionAdapter(
070: componentImplementation, componentMonitor,
071: lifecycleStrategy, componentProperties, componentKey,
072: componentAdapter, parameters);
073:
074: if (componentAdapter != null) {
075: return componentAdapter;
076: }
077:
078: componentAdapter = setterInjectionAdapter(componentProperties,
079: componentMonitor, lifecycleStrategy, componentKey,
080: componentImplementation, componentAdapter, parameters);
081:
082: if (componentAdapter != null) {
083: return componentAdapter;
084: }
085:
086: componentAdapter = methodInjectionAdapter(componentProperties,
087: componentMonitor, lifecycleStrategy, componentKey,
088: componentImplementation, componentAdapter, parameters);
089:
090: if (componentAdapter != null) {
091: return componentAdapter;
092: }
093:
094: return defaultInjectionAdapter(componentProperties,
095: componentMonitor, lifecycleStrategy, componentKey,
096: componentImplementation, parameters);
097: }
098:
099: private <T> ComponentAdapter<T> defaultInjectionAdapter(
100: Properties componentProperties,
101: ComponentMonitor componentMonitor,
102: LifecycleStrategy lifecycleStrategy, Object componentKey,
103: Class<T> componentImplementation, Parameter... parameters) {
104: AbstractBehaviorFactory.removePropertiesIfPresent(
105: componentProperties, Characteristics.CDI);
106: return new ConstructorInjection().createComponentAdapter(
107: componentMonitor, lifecycleStrategy,
108: componentProperties, componentKey,
109: componentImplementation, parameters);
110: }
111:
112: private <T> ComponentAdapter<T> setterInjectionAdapter(
113: Properties componentProperties,
114: ComponentMonitor componentMonitor,
115: LifecycleStrategy lifecycleStrategy, Object componentKey,
116: Class<T> componentImplementation,
117: ComponentAdapter<T> componentAdapter,
118: Parameter... parameters) {
119: if (AbstractBehaviorFactory.removePropertiesIfPresent(
120: componentProperties, Characteristics.SDI)) {
121: componentAdapter = new SetterInjection()
122: .createComponentAdapter(componentMonitor,
123: lifecycleStrategy, componentProperties,
124: componentKey, componentImplementation,
125: parameters);
126: }
127: return componentAdapter;
128: }
129:
130: private <T> ComponentAdapter<T> methodInjectionAdapter(
131: Properties componentProperties,
132: ComponentMonitor componentMonitor,
133: LifecycleStrategy lifecycleStrategy, Object componentKey,
134: Class<T> componentImplementation,
135: ComponentAdapter<T> componentAdapter,
136: Parameter... parameters) {
137: if (AbstractBehaviorFactory.removePropertiesIfPresent(
138: componentProperties, Characteristics.METHOD_INJECTION)) {
139: componentAdapter = new MethodInjection()
140: .createComponentAdapter(componentMonitor,
141: lifecycleStrategy, componentProperties,
142: componentKey, componentImplementation,
143: parameters);
144: }
145: return componentAdapter;
146: }
147:
148: private <T> ComponentAdapter<T> methodAnnotatedInjectionAdapter(
149: Class<T> componentImplementation,
150: ComponentMonitor componentMonitor,
151: LifecycleStrategy lifecycleStrategy,
152: Properties componentProperties, Object componentKey,
153: ComponentAdapter<T> componentAdapter,
154: Parameter... parameters) {
155: if (injectionMethodAnnotated(componentImplementation)) {
156: componentAdapter = new AnnotatedMethodInjection()
157: .createComponentAdapter(componentMonitor,
158: lifecycleStrategy, componentProperties,
159: componentKey, componentImplementation,
160: parameters);
161: }
162: return componentAdapter;
163: }
164:
165: private <T> ComponentAdapter<T> fieldAnnotatedInjectionAdapter(
166: Class<T> componentImplementation,
167: ComponentMonitor componentMonitor,
168: LifecycleStrategy lifecycleStrategy,
169: Properties componentProperties, Object componentKey,
170: ComponentAdapter<T> componentAdapter,
171: Parameter... parameters) {
172: if (injectionFieldAnnotated(componentImplementation)) {
173: componentAdapter = new AnnotatedFieldInjection()
174: .createComponentAdapter(componentMonitor,
175: lifecycleStrategy, componentProperties,
176: componentKey, componentImplementation,
177: parameters);
178: }
179: return componentAdapter;
180: }
181:
182: private boolean injectionMethodAnnotated(
183: Class<?> componentImplementation) {
184: return injectionAnnotated(componentImplementation
185: .getDeclaredMethods());
186: }
187:
188: private boolean injectionFieldAnnotated(
189: Class<?> componentImplementation) {
190: return injectionAnnotated(componentImplementation
191: .getDeclaredFields());
192: }
193:
194: private boolean injectionAnnotated(AccessibleObject[] objects) {
195: for (AccessibleObject object : objects) {
196: if (object.getAnnotation(Inject.class) != null) {
197: return true;
198: }
199: }
200: return false;
201: }
202:
203: }
|