KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > picocontainer > defaults > SetterInjectionComponentAdapter


1 /*****************************************************************************
2  * Copyright (C) PicoContainer Organization. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  * *
8  * Original code by *
9  *****************************************************************************/

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 JavaDoc;
18 import java.lang.reflect.InvocationTargetException JavaDoc;
19 import java.lang.reflect.Method JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Set JavaDoc;
25
26 /**
27  * Instantiates components using empty constructors and
28  * <a HREF="http://docs.codehaus.org/display/PICO/Setter+Injection">Setter Injection</a>.
29  * For easy setting of primitive properties, also see {@link BeanPropertyComponentAdapter}.
30  * <p/>
31  * <em>
32  * Note that this class doesn't cache instances. If you want caching,
33  * use a {@link CachingComponentAdapter} around this one.
34  * </em>
35  *
36  * @author Aslak Helles&oslash;y
37  * @author J&ouml;rg Schaible
38  * @version $Revision: 1820 $
39  */

40 public class SetterInjectionComponentAdapter extends InstantiatingComponentAdapter {
41     private transient Guard instantiationGuard;
42     private transient List JavaDoc setters;
43     private transient List JavaDoc setterNames;
44     private transient Class JavaDoc[] setterTypes;
45
46     /**
47      * {@inheritDoc}
48      * Explicitly specifies parameters, if null uses default parameters.
49      */

50     public SetterInjectionComponentAdapter(final Object JavaDoc componentKey,
51                                            final Class JavaDoc componentImplementation,
52                                            Parameter[] parameters,
53                                            boolean allowNonPublicClasses) throws AssignabilityRegistrationException, NotConcreteRegistrationException {
54         super(componentKey, componentImplementation, parameters, allowNonPublicClasses);
55     }
56
57     public SetterInjectionComponentAdapter(final Object JavaDoc componentKey,
58                                            final Class JavaDoc componentImplementation,
59                                            Parameter[] parameters) throws AssignabilityRegistrationException, NotConcreteRegistrationException {
60         super(componentKey, componentImplementation, parameters, false);
61     }
62
63     protected Constructor JavaDoc getGreediestSatisfiableConstructor(PicoContainer container) throws PicoIntrospectionException, UnsatisfiableDependenciesException, AmbiguousComponentResolutionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
64         final Constructor JavaDoc constructor = getConstructor();
65         getMatchingParameterListForSetters(container);
66         return constructor;
67     }
68     
69     private Constructor JavaDoc getConstructor() throws PicoInvocationTargetInitializationException {
70         final Constructor JavaDoc constructor;
71         try {
72             constructor = getComponentImplementation().getConstructor(null);
73         } catch (NoSuchMethodException JavaDoc e) {
74             throw new PicoInvocationTargetInitializationException(e);
75         } catch (SecurityException JavaDoc 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 JavaDoc matchingParameterList = new ArrayList JavaDoc(Collections.nCopies(setters.size(), null));
88         final Set JavaDoc nonMatchingParameterPositions = new HashSet JavaDoc();
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 JavaDoc(i));
102             }
103         }
104
105         final Set JavaDoc unsatisfiableDependencyTypes = new HashSet JavaDoc();
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 JavaDoc getComponentInstance(final PicoContainer container) throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
121         final Constructor JavaDoc constructor = getConstructor();
122         if (instantiationGuard == null) {
123             instantiationGuard = new Guard() {
124                 public Object JavaDoc run() {
125                     final Parameter[] matchingParameters = getMatchingParameterListForSetters(guardedContainer);
126                     try {
127                         final Object JavaDoc componentInstance = newInstance(constructor, null);
128                         for (int i = 0; i < setters.size(); i++) {
129                             final Method JavaDoc setter = (Method JavaDoc) setters.get(i);
130                             setter.invoke(componentInstance, new Object JavaDoc[]{matchingParameters[i].resolveInstance(guardedContainer, SetterInjectionComponentAdapter.this, setterTypes[i])});
131                         }
132                         return componentInstance;
133                     } catch (InvocationTargetException JavaDoc e) {
134                         if (e.getTargetException() instanceof RuntimeException JavaDoc) {
135                             throw (RuntimeException JavaDoc) e.getTargetException();
136                         } else if (e.getTargetException() instanceof Error JavaDoc) {
137                             throw (Error JavaDoc) e.getTargetException();
138                         }
139                         throw new PicoInvocationTargetInitializationException(e.getTargetException());
140                     } catch (InstantiationException JavaDoc e) {
141                         throw new PicoInvocationTargetInitializationException(e);
142                     } catch (IllegalAccessException JavaDoc 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 JavaDoc 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 JavaDoc();
170         setterNames = new ArrayList JavaDoc();
171         final List JavaDoc typeList = new ArrayList JavaDoc();
172         final Method JavaDoc[] methods = getComponentImplementation().getMethods();
173         for (int i = 0; i < methods.length; i++) {
174             final Method JavaDoc method = methods[i];
175             final Class JavaDoc[] parameterTypes = method.getParameterTypes();
176             // We're only interested if there is only one parameter and the method name is bean-style.
177
if (parameterTypes.length == 1) {
178                 String JavaDoc methodName = method.getName();
179                 boolean isBeanStyle = methodName.length() >= 4 && methodName.startsWith("set") && Character.isUpperCase(methodName.charAt(3));
180                 if (isBeanStyle) {
181                     String JavaDoc 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 JavaDoc[]) typeList.toArray(new Class JavaDoc[0]);
189     }
190 }
191
Popular Tags