1 10 package org.picocontainer.defaults; 11 12 import org.picocontainer.Parameter; 13 import org.picocontainer.PicoContainer; 14 import org.picocontainer.PicoInitializationException; 15 import org.picocontainer.PicoIntrospectionException; 16 17 import java.lang.reflect.Constructor ; 18 import java.lang.reflect.InvocationTargetException ; 19 import java.lang.reflect.Method ; 20 import java.util.ArrayList ; 21 import java.util.Collections ; 22 import java.util.HashSet ; 23 import java.util.List ; 24 import java.util.Set ; 25 26 40 public class SetterInjectionComponentAdapter extends InstantiatingComponentAdapter { 41 private transient Guard instantiationGuard; 42 private transient List setters; 43 private transient List setterNames; 44 private transient Class [] setterTypes; 45 46 50 public SetterInjectionComponentAdapter(final Object componentKey, 51 final Class componentImplementation, 52 Parameter[] parameters, 53 boolean allowNonPublicClasses) throws AssignabilityRegistrationException, NotConcreteRegistrationException { 54 super(componentKey, componentImplementation, parameters, allowNonPublicClasses); 55 } 56 57 public SetterInjectionComponentAdapter(final Object componentKey, 58 final Class componentImplementation, 59 Parameter[] parameters) throws AssignabilityRegistrationException, NotConcreteRegistrationException { 60 super(componentKey, componentImplementation, parameters, false); 61 } 62 63 protected Constructor getGreediestSatisfiableConstructor(PicoContainer container) throws PicoIntrospectionException, UnsatisfiableDependenciesException, AmbiguousComponentResolutionException, AssignabilityRegistrationException, NotConcreteRegistrationException { 64 final Constructor constructor = getConstructor(); 65 getMatchingParameterListForSetters(container); 66 return constructor; 67 } 68 69 private Constructor getConstructor() throws PicoInvocationTargetInitializationException { 70 final Constructor constructor; 71 try { 72 constructor = getComponentImplementation().getConstructor(null); 73 } catch (NoSuchMethodException e) { 74 throw new PicoInvocationTargetInitializationException(e); 75 } catch (SecurityException e) { 76 throw new PicoInvocationTargetInitializationException(e); 77 } 78 79 return constructor; 80 } 81 82 private Parameter[] getMatchingParameterListForSetters(PicoContainer container) throws PicoInitializationException, UnsatisfiableDependenciesException { 83 if (setters == null) { 84 initializeSetterAndTypeLists(); 85 } 86 87 final List matchingParameterList = new ArrayList (Collections.nCopies(setters.size(), null)); 88 final Set nonMatchingParameterPositions = new HashSet (); 89 final Parameter[] currentParameters = parameters != null ? parameters : createDefaultParameters(setterTypes); 90 for (int i = 0; i < currentParameters.length; i++) { 91 final Parameter parameter = currentParameters[i]; 92 boolean failedDependency = true; 93 for (int j = 0; j < setterTypes.length; j++) { 94 if (matchingParameterList.get(j) == null && parameter.isResolvable(container, this, setterTypes[j])) { 95 matchingParameterList.set(j, parameter); 96 failedDependency = false; 97 break; 98 } 99 } 100 if (failedDependency) { 101 nonMatchingParameterPositions.add(new Integer (i)); 102 } 103 } 104 105 final Set unsatisfiableDependencyTypes = new HashSet (); 106 for (int i = 0; i < matchingParameterList.size(); i++) { 107 if (matchingParameterList.get(i) == null) { 108 unsatisfiableDependencyTypes.add(setterTypes[i]); 109 } 110 } 111 if (unsatisfiableDependencyTypes.size() > 0) { 112 throw new UnsatisfiableDependenciesException(this, unsatisfiableDependencyTypes); 113 } else if (nonMatchingParameterPositions.size() > 0) { 114 throw new PicoInitializationException("Following parameters do not match any of the setters for " 115 + getComponentImplementation() + ": " + nonMatchingParameterPositions.toString()); 116 } 117 return (Parameter[]) matchingParameterList.toArray(new Parameter[matchingParameterList.size()]); 118 } 119 120 public Object getComponentInstance(final PicoContainer container) throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException { 121 final Constructor constructor = getConstructor(); 122 if (instantiationGuard == null) { 123 instantiationGuard = new Guard() { 124 public Object run() { 125 final Parameter[] matchingParameters = getMatchingParameterListForSetters(guardedContainer); 126 try { 127 final Object componentInstance = newInstance(constructor, null); 128 for (int i = 0; i < setters.size(); i++) { 129 final Method setter = (Method ) setters.get(i); 130 setter.invoke(componentInstance, new Object []{matchingParameters[i].resolveInstance(guardedContainer, SetterInjectionComponentAdapter.this, setterTypes[i])}); 131 } 132 return componentInstance; 133 } catch (InvocationTargetException e) { 134 if (e.getTargetException() instanceof RuntimeException ) { 135 throw (RuntimeException ) e.getTargetException(); 136 } else if (e.getTargetException() instanceof Error ) { 137 throw (Error ) e.getTargetException(); 138 } 139 throw new PicoInvocationTargetInitializationException(e.getTargetException()); 140 } catch (InstantiationException e) { 141 throw new PicoInvocationTargetInitializationException(e); 142 } catch (IllegalAccessException e) { 143 throw new PicoInvocationTargetInitializationException(e); 144 } 145 } 146 }; 147 } 148 instantiationGuard.setArguments(container); 149 return instantiationGuard.observe(getComponentImplementation()); 150 } 151 152 public void verify(final PicoContainer container) throws PicoIntrospectionException { 153 if (verifyingGuard == null) { 154 verifyingGuard = new Guard() { 155 public Object run() { 156 final Parameter[] currentParameters = getMatchingParameterListForSetters(guardedContainer); 157 for (int i = 0; i < currentParameters.length; i++) { 158 currentParameters[i].verify(container, SetterInjectionComponentAdapter.this, setterTypes[i]); 159 } 160 return null; 161 } 162 }; 163 } 164 verifyingGuard.setArguments(container); 165 verifyingGuard.observe(getComponentImplementation()); 166 } 167 168 private void initializeSetterAndTypeLists() { 169 setters = new ArrayList (); 170 setterNames = new ArrayList (); 171 final List typeList = new ArrayList (); 172 final Method [] methods = getComponentImplementation().getMethods(); 173 for (int i = 0; i < methods.length; i++) { 174 final Method method = methods[i]; 175 final Class [] parameterTypes = method.getParameterTypes(); 176 if (parameterTypes.length == 1) { 178 String methodName = method.getName(); 179 boolean isBeanStyle = methodName.length() >= 4 && methodName.startsWith("set") && Character.isUpperCase(methodName.charAt(3)); 180 if (isBeanStyle) { 181 String attribute = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); 182 setters.add(method); 183 setterNames.add(attribute); 184 typeList.add(parameterTypes[0]); 185 } 186 } 187 } 188 setterTypes = (Class []) typeList.toArray(new Class [0]); 189 } 190 } 191 | Popular Tags |