Clover coverage report - PicoContainer - 1.1
Coverage timestamp: Thu Nov 4 2004 11:55:45 CST
file stats: LOC: 164   Methods: 5
NCLOC: 96   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 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: 1.11 $
 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   
 }