Clover coverage report - picocontainer - 1.2-beta-1
Coverage timestamp: Sun May 29 2005 14:29:04 BST
file stats: LOC: 190   Methods: 10
NCLOC: 148   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
SetterInjectionComponentAdapter.java 97.4% 91% 90% 92.9%
coverage coverage
 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;
 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    /**
 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 setters;
 43    private transient List setterNames;
 44    private transient Class[] setterTypes;
 45   
 46    /**
 47    * {@inheritDoc}
 48    * Explicitly specifies parameters, if null uses default parameters.
 49    */
 50  20 public SetterInjectionComponentAdapter(final Object componentKey,
 51    final Class componentImplementation,
 52    Parameter[] parameters,
 53    boolean allowNonPublicClasses) throws AssignabilityRegistrationException, NotConcreteRegistrationException {
 54  20 super(componentKey, componentImplementation, parameters, allowNonPublicClasses);
 55    }
 56   
 57  38 public SetterInjectionComponentAdapter(final Object componentKey,
 58    final Class componentImplementation,
 59    Parameter[] parameters) throws AssignabilityRegistrationException, NotConcreteRegistrationException {
 60  38 super(componentKey, componentImplementation, parameters, false);
 61    }
 62   
 63  0 protected Constructor getGreediestSatisfiableConstructor(PicoContainer container) throws PicoIntrospectionException, UnsatisfiableDependenciesException, AmbiguousComponentResolutionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
 64  0 final Constructor constructor = getConstructor();
 65  0 getMatchingParameterListForSetters(container);
 66  0 return constructor;
 67    }
 68   
 69  50 private Constructor getConstructor() throws PicoInvocationTargetInitializationException {
 70  50 final Constructor constructor;
 71  50 try {
 72  50 constructor = getComponentImplementation().getConstructor(null);
 73    } catch (NoSuchMethodException e) {
 74  2 throw new PicoInvocationTargetInitializationException(e);
 75    } catch (SecurityException e) {
 76  0 throw new PicoInvocationTargetInitializationException(e);
 77    }
 78   
 79  48 return constructor;
 80    }
 81   
 82  56 private Parameter[] getMatchingParameterListForSetters(PicoContainer container) throws PicoInitializationException, UnsatisfiableDependenciesException {
 83  56 if (setters == null) {
 84  48 initializeSetterAndTypeLists();
 85    }
 86   
 87  56 final List matchingParameterList = new ArrayList(Collections.nCopies(setters.size(), null));
 88  56 final Set nonMatchingParameterPositions = new HashSet();
 89  56 final Parameter[] currentParameters = parameters != null ? parameters : createDefaultParameters(setterTypes);
 90  56 for (int i = 0; i < currentParameters.length; i++) {
 91  66 final Parameter parameter = currentParameters[i];
 92  66 boolean failedDependency = true;
 93  66 for (int j = 0; j < setterTypes.length; j++) {
 94  88 if (matchingParameterList.get(j) == null && parameter.isResolvable(container, this, setterTypes[j])) {
 95  62 matchingParameterList.set(j, parameter);
 96  62 failedDependency = false;
 97  62 break;
 98    }
 99    }
 100  66 if (failedDependency) {
 101  4 nonMatchingParameterPositions.add(new Integer(i));
 102    }
 103    }
 104   
 105  56 final Set unsatisfiableDependencyTypes = new HashSet();
 106  56 for (int i = 0; i < matchingParameterList.size(); i++) {
 107  70 if (matchingParameterList.get(i) == null) {
 108  8 unsatisfiableDependencyTypes.add(setterTypes[i]);
 109    }
 110    }
 111  56 if (unsatisfiableDependencyTypes.size() > 0) {
 112  6 throw new UnsatisfiableDependenciesException(this, unsatisfiableDependencyTypes);
 113  50 } else if (nonMatchingParameterPositions.size() > 0) {
 114  0 throw new PicoInitializationException("Following parameters do not match any of the setters for "
 115    + getComponentImplementation() + ": " + nonMatchingParameterPositions.toString());
 116    }
 117  50 return (Parameter[]) matchingParameterList.toArray(new Parameter[matchingParameterList.size()]);
 118    }
 119   
 120  50 public Object getComponentInstance(final PicoContainer container) throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
 121  50 final Constructor constructor = getConstructor();
 122  48 if (instantiationGuard == null) {
 123  40 instantiationGuard = new Guard() {
 124  46 public Object run() {
 125  46 final Parameter[] matchingParameters = getMatchingParameterListForSetters(guardedContainer);
 126  42 try {
 127  42 final Object componentInstance = newInstance(constructor, null);
 128  36 for (int i = 0; i < setters.size(); i++) {
 129  38 final Method setter = (Method) setters.get(i);
 130  38 setter.invoke(componentInstance, new Object[]{matchingParameters[i].resolveInstance(guardedContainer, SetterInjectionComponentAdapter.this, setterTypes[i])});
 131    }
 132  32 return componentInstance;
 133    } catch (InvocationTargetException e) {
 134  6 if (e.getTargetException() instanceof RuntimeException) {
 135  2 throw (RuntimeException) e.getTargetException();
 136  4 } else if (e.getTargetException() instanceof Error) {
 137  2 throw (Error) e.getTargetException();
 138    }
 139  2 throw new PicoInvocationTargetInitializationException(e.getTargetException());
 140    } catch (InstantiationException e) {
 141  0 throw new PicoInvocationTargetInitializationException(e);
 142    } catch (IllegalAccessException e) {
 143  0 throw new PicoInvocationTargetInitializationException(e);
 144    }
 145    }
 146    };
 147    }
 148  48 instantiationGuard.setArguments(container);
 149  48 return instantiationGuard.observe(getComponentImplementation());
 150    }
 151   
 152  12 public void verify(final PicoContainer container) throws PicoIntrospectionException {
 153  12 if (verifyingGuard == null) {
 154  10 verifyingGuard = new Guard() {
 155  10 public Object run() {
 156  10 final Parameter[] currentParameters = getMatchingParameterListForSetters(guardedContainer);
 157  8 for (int i = 0; i < currentParameters.length; i++) {
 158  8 currentParameters[i].verify(container, SetterInjectionComponentAdapter.this, setterTypes[i]);
 159    }
 160  4 return null;
 161    }
 162    };
 163    }
 164  12 verifyingGuard.setArguments(container);
 165  12 verifyingGuard.observe(getComponentImplementation());
 166    }
 167   
 168  48 private void initializeSetterAndTypeLists() {
 169  48 setters = new ArrayList();
 170  48 setterNames = new ArrayList();
 171  48 final List typeList = new ArrayList();
 172  48 final Method[] methods = getComponentImplementation().getMethods();
 173  48 for (int i = 0; i < methods.length; i++) {
 174  562 final Method method = methods[i];
 175  562 final Class[] parameterTypes = method.getParameterTypes();
 176    // We're only interested if there is only one parameter and the method name is bean-style.
 177  562 if (parameterTypes.length == 1) {
 178  158 String methodName = method.getName();
 179  158 boolean isBeanStyle = methodName.length() >= 4 && methodName.startsWith("set") && Character.isUpperCase(methodName.charAt(3));
 180  158 if (isBeanStyle) {
 181  62 String attribute = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
 182  62 setters.add(method);
 183  62 setterNames.add(attribute);
 184  62 typeList.add(parameterTypes[0]);
 185    }
 186    }
 187    }
 188  48 setterTypes = (Class[]) typeList.toArray(new Class[0]);
 189    }
 190    }