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 *****************************************************************************/ 010 011 package org.picocontainer.injectors; 012 013 import java.lang.reflect.AccessibleObject; 014 import java.util.Properties; 015 016 import org.picocontainer.Characteristics; 017 import org.picocontainer.ComponentAdapter; 018 import org.picocontainer.ComponentMonitor; 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 @SuppressWarnings("serial") 045 public class AdaptingInjection extends AbstractInjectionFactory { 046 047 048 public <T> ComponentAdapter<T> createComponentAdapter(ComponentMonitor componentMonitor, 049 LifecycleStrategy lifecycleStrategy, 050 Properties componentProperties, 051 Object componentKey, 052 Class<T> componentImplementation, 053 Parameter... parameters) throws PicoCompositionException { 054 ComponentAdapter<T> componentAdapter = null; 055 056 componentAdapter = fieldAnnotatedInjectionAdapter(componentImplementation, 057 componentMonitor, 058 lifecycleStrategy, 059 componentProperties, 060 componentKey, 061 componentAdapter, 062 parameters); 063 064 if (componentAdapter != null) { 065 return componentAdapter; 066 } 067 068 069 componentAdapter = methodAnnotatedInjectionAdapter(componentImplementation, 070 componentMonitor, 071 lifecycleStrategy, 072 componentProperties, 073 componentKey, 074 componentAdapter, 075 parameters); 076 077 if (componentAdapter != null) { 078 return componentAdapter; 079 } 080 081 componentAdapter = setterInjectionAdapter(componentProperties, 082 componentMonitor, 083 lifecycleStrategy, 084 componentKey, 085 componentImplementation, 086 componentAdapter, 087 parameters); 088 089 if (componentAdapter != null) { 090 return componentAdapter; 091 } 092 093 componentAdapter = methodInjectionAdapter(componentProperties, 094 componentMonitor, 095 lifecycleStrategy, 096 componentKey, 097 componentImplementation, 098 componentAdapter, 099 parameters); 100 101 if (componentAdapter != null) { 102 return componentAdapter; 103 } 104 105 106 return defaultInjectionAdapter(componentProperties, 107 componentMonitor, 108 lifecycleStrategy, 109 componentKey, 110 componentImplementation, 111 parameters); 112 } 113 114 private <T> ComponentAdapter<T> defaultInjectionAdapter(Properties componentProperties, 115 ComponentMonitor componentMonitor, 116 LifecycleStrategy lifecycleStrategy, 117 Object componentKey, 118 Class<T> componentImplementation, Parameter... parameters) { 119 AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.CDI); 120 return new ConstructorInjection().createComponentAdapter(componentMonitor, 121 lifecycleStrategy, 122 componentProperties, 123 componentKey, 124 componentImplementation, 125 parameters); 126 } 127 128 private <T> ComponentAdapter<T> setterInjectionAdapter(Properties componentProperties, 129 ComponentMonitor componentMonitor, 130 LifecycleStrategy lifecycleStrategy, 131 Object componentKey, 132 Class<T> componentImplementation, 133 ComponentAdapter<T> componentAdapter, 134 Parameter... parameters) { 135 if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.SDI)) { 136 componentAdapter = new SetterInjection().createComponentAdapter(componentMonitor, lifecycleStrategy, 137 componentProperties, 138 componentKey, 139 componentImplementation, 140 parameters); 141 } 142 return componentAdapter; 143 } 144 145 private <T> ComponentAdapter<T> methodInjectionAdapter(Properties componentProperties, 146 ComponentMonitor componentMonitor, 147 LifecycleStrategy lifecycleStrategy, 148 Object componentKey, 149 Class<T> componentImplementation, 150 ComponentAdapter<T> componentAdapter, 151 Parameter... parameters) { 152 if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.METHOD_INJECTION)) { 153 componentAdapter = new MethodInjection().createComponentAdapter(componentMonitor, lifecycleStrategy, 154 componentProperties, 155 componentKey, 156 componentImplementation, 157 parameters); 158 } 159 return componentAdapter; 160 } 161 162 163 private <T> ComponentAdapter<T> methodAnnotatedInjectionAdapter(Class<T> componentImplementation, 164 ComponentMonitor componentMonitor, 165 LifecycleStrategy lifecycleStrategy, 166 Properties componentProperties, 167 Object componentKey, 168 ComponentAdapter<T> componentAdapter, 169 Parameter... parameters) { 170 if (injectionMethodAnnotated(componentImplementation)) { 171 componentAdapter = 172 new AnnotatedMethodInjection().createComponentAdapter(componentMonitor, 173 lifecycleStrategy, 174 componentProperties, 175 componentKey, 176 componentImplementation, 177 parameters); 178 } 179 return componentAdapter; 180 } 181 182 private <T> ComponentAdapter<T> fieldAnnotatedInjectionAdapter(Class<T> componentImplementation, 183 ComponentMonitor componentMonitor, 184 LifecycleStrategy lifecycleStrategy, 185 Properties componentProperties, 186 Object componentKey, ComponentAdapter<T> componentAdapter, Parameter... parameters) { 187 if (injectionFieldAnnotated(componentImplementation)) { 188 componentAdapter = 189 new AnnotatedFieldInjection().createComponentAdapter(componentMonitor, 190 lifecycleStrategy, 191 componentProperties, 192 componentKey, 193 componentImplementation, 194 parameters); 195 } 196 return componentAdapter; 197 } 198 199 private boolean injectionMethodAnnotated(Class<?> componentImplementation) { 200 return injectionAnnotated(componentImplementation.getDeclaredMethods()); 201 } 202 203 private boolean injectionFieldAnnotated(Class<?> componentImplementation) { 204 return injectionAnnotated(componentImplementation.getDeclaredFields()); 205 } 206 207 private boolean injectionAnnotated(AccessibleObject[] objects) { 208 for (AccessibleObject object : objects) { 209 if (object.getAnnotation(Inject.class) != null) { 210 return true; 211 } 212 } 213 return false; 214 } 215 216 }