Clover coverage report - picocontainer - 1.2-beta-1
Coverage timestamp: Sun May 29 2005 14:29:04 BST
file stats: LOC: 164   Methods: 5
NCLOC: 96   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
BeanPropertyComponentAdapter.java 86.8% 94.7% 100% 92%
coverage coverage
 1    package org.picocontainer.defaults;
 2   
 3    import org.picocontainer.ComponentAdapter;
 4    import org.picocontainer.PicoContainer;
 5    import org.picocontainer.PicoInitializationException;
 6    import org.picocontainer.PicoIntrospectionException;
 7   
 8    import java.io.File;
 9    import java.lang.reflect.Method;
 10    import java.net.MalformedURLException;
 11    import java.net.URL;
 12    import java.util.Iterator;
 13    import java.util.Map;
 14    import java.util.Set;
 15   
 16    /**
 17    * Decorating component adapter that can be used to set additional properties
 18    * on a component in a bean style. These properties must be managed manually
 19    * by the user of the API, and will not be managed by PicoContainer. This class
 20    * is therefore <em>not</em> the same as {@link SetterInjectionComponentAdapter},
 21    * which is a true Setter Injection adapter.
 22    * <p/>
 23    * This adapter is mostly handy for setting various primitive properties via setters.
 24    * <p/>
 25    * <em>
 26    * Note that this class doesn't cache instances. If you want caching,
 27    * use a {@link CachingComponentAdapter} around this one.
 28    * </em>
 29    *
 30    * @author Aslak Helles&oslash;y
 31    * @version $Revision: 1812 $
 32    * @since 1.0
 33    */
 34    public class BeanPropertyComponentAdapter extends DecoratingComponentAdapter {
 35    private Map properties;
 36    private transient Map setters = null;
 37   
 38    /**
 39    * Construct a BeanProeprtyComponentAdapter.
 40    *
 41    * @param delegate the wrapped {@link ComponentAdapter}
 42    * @throws PicoInitializationException {@inheritDoc}
 43    */
 44  18 public BeanPropertyComponentAdapter(ComponentAdapter delegate) throws PicoInitializationException {
 45  18 super(delegate);
 46    }
 47   
 48    /**
 49    * Get a component instance and set given property values.
 50    *
 51    * @return the component instance with any properties of the properties map set.
 52    * @throws PicoInitializationException {@inheritDoc}
 53    * @throws PicoIntrospectionException {@inheritDoc}
 54    * @throws AssignabilityRegistrationException
 55    * {@inheritDoc}
 56    * @throws NotConcreteRegistrationException
 57    * {@inheritDoc}
 58    * @see #setProperties(Map)
 59    */
 60  10 public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
 61  10 final Object componentInstance = super.getComponentInstance(container);
 62  10 if (setters == null) {
 63  10 setters = new SetterIntrospector().getSetters(getComponentImplementation());
 64    }
 65   
 66  10 if (properties != null) {
 67  10 Set propertyNames = properties.keySet();
 68  10 for (Iterator iterator = propertyNames.iterator(); iterator.hasNext();) {
 69  32 final String propertyName = (String) iterator.next();
 70  32 final String propertyValue = (String) properties.get(propertyName);
 71  32 Method setter = (Method) setters.get(propertyName);
 72  32 Object value = null;
 73  32 try {
 74  32 value = convertType(container, setter, propertyValue);
 75    } catch (ClassNotFoundException e) {
 76  0 throw new PicoInvocationTargetInitializationException(e);
 77    }
 78  32 try {
 79  32 setter.invoke(componentInstance, new Object[]{value});
 80    } catch (final Exception e) {
 81  2 throw new PicoInitializationException("Failed to set property " + propertyName + " to " + propertyValue + ": " + e.getMessage(), e);
 82    }
 83    }
 84    }
 85  8 return componentInstance;
 86    }
 87   
 88  32 private Object convertType(PicoContainer container, Method setter, String propertyValue) throws ClassNotFoundException {
 89  32 if (propertyValue == null) {
 90  0 return null;
 91    }
 92  32 Class type = setter.getParameterTypes()[0];
 93  32 String typeName = type.getName();
 94   
 95  32 Object result = convert(typeName, propertyValue, Thread.currentThread().getContextClassLoader());
 96   
 97  32 if (result == null) {
 98   
 99    // check if the propertyValue is a key of a component in the container
 100    // if so, the typeName of the component and the setters parameter typeName
 101    // have to be compatible
 102   
 103    // TODO: null check only because of test-case, otherwise null is impossible
 104  2 if (container != null) {
 105  2 Object component = container.getComponentInstance(propertyValue);
 106  2 if (component != null && type.isAssignableFrom(component.getClass())) {
 107  2 return component;
 108    }
 109    }
 110    }
 111  30 return result;
 112    }
 113   
 114    /**
 115    * Converts a type name to an object.
 116    *
 117    * @param typeName name of the type
 118    * @param value its value
 119    * @param classLoader used to load a class if typeName is "class" or "java.lang.Class" (ignored otherwise)
 120    * @return instantiated object or null if the type was unknown/unsupported
 121    * @throws ClassNotFoundException if typeName is "class" or "java.lang.Class" and class couldn't be loaded.
 122    */
 123  32 public static Object convert(String typeName, String value, ClassLoader classLoader) throws ClassNotFoundException {
 124  32 if (typeName.equals(Boolean.class.getName()) || typeName.equals(boolean.class.getName())) {
 125  2 return Boolean.valueOf(value);
 126  30 } else if (typeName.equals(Byte.class.getName()) || typeName.equals(byte.class.getName())) {
 127  2 return Byte.valueOf(value);
 128  28 } else if (typeName.equals(Short.class.getName()) || typeName.equals(short.class.getName())) {
 129  2 return Short.valueOf(value);
 130  26 } else if (typeName.equals(Integer.class.getName()) || typeName.equals(int.class.getName())) {
 131  2 return Integer.valueOf(value);
 132  24 } else if (typeName.equals(Long.class.getName()) || typeName.equals(long.class.getName())) {
 133  2 return Long.valueOf(value);
 134  22 } else if (typeName.equals(Float.class.getName()) || typeName.equals(float.class.getName())) {
 135  2 return Float.valueOf(value);
 136  20 } else if (typeName.equals(Double.class.getName()) || typeName.equals(double.class.getName())) {
 137  2 return Double.valueOf(value);
 138  18 } else if (typeName.equals(Character.class.getName()) || typeName.equals(char.class.getName())) {
 139  2 return new Character(value.toCharArray()[0]);
 140  16 } else if (typeName.equals(String.class.getName()) || typeName.equals("string")) {
 141  8 return value;
 142  8 } else if (typeName.equals(File.class.getName()) || typeName.equals("file")) {
 143  2 return new File(value);
 144  6 } else if (typeName.equals(URL.class.getName()) || typeName.equals("url")) {
 145  2 try {
 146  2 return new URL(value);
 147    } catch (MalformedURLException e) {
 148  0 throw new PicoInitializationException(e);
 149    }
 150  4 } else if (typeName.equals(Class.class.getName()) || typeName.equals("class")) {
 151  2 return classLoader.loadClass(value);
 152    }
 153  2 return null;
 154    }
 155   
 156    /**
 157    * Sets the bean property values that should be set upon creation.
 158    *
 159    * @param properties bean properties
 160    */
 161  10 public void setProperties(Map properties) {
 162  10 this.properties = properties;
 163    }
 164    }