Clover coverage report - PicoContainer - 1.0-alpha-2
Coverage timestamp: Thu Jul 10 2003 10:40:43 BST
file stats: LOC: 308   Methods: 24
NCLOC: 212   Classes: 2
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
DefaultPicoContainer.java 100% 100% 100% 100%
coverage
 1   
 /*****************************************************************************
 2   
  * Copyright (Cc) 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   
  * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant   *
 9   
  *****************************************************************************/
 10   
 
 11   
 package picocontainer.defaults;
 12   
 
 13   
 import picocontainer.ComponentFactory;
 14   
 import picocontainer.ComponentFactory;
 15   
 import picocontainer.PicoInstantiationException;
 16   
 import picocontainer.PicoRegistrationException;
 17   
 import picocontainer.PicoInstantiationException;
 18   
 import picocontainer.PicoIntrospectionException;
 19   
 import picocontainer.ClassRegistrationPicoContainer;
 20   
 
 21   
 import java.util.Set;
 22   
 import java.util.List;
 23   
 import java.util.Map;
 24   
 import java.util.HashMap;
 25   
 import java.util.ArrayList;
 26   
 import java.util.Iterator;
 27   
 import java.lang.reflect.Modifier;
 28   
 
 29   
 /**
 30   
  * Abstract baseclass for various PicoContainer implementations.
 31   
  *
 32   
  * @author Aslak Hellesoy
 33   
  * @version $Revision: 1.8 $
 34   
  */
 35   
 public class DefaultPicoContainer implements ClassRegistrationPicoContainer {
 36   
 
 37   
     private final ComponentFactory componentFactory;
 38   
     private List registeredComponents = new ArrayList();
 39   
     private Map componentTypeToInstanceMap = new HashMap();
 40   
 
 41   
     // Keeps track of the instantiation order
 42   
     protected List orderedComponents = new ArrayList();
 43   
 
 44   
     // Keeps track of unmanaged components - components instantiated outside this container
 45   
     protected List unmanagedComponents = new ArrayList();
 46   
 
 47   
     private boolean initialized;
 48   
     private Map componentToSpec = new HashMap();
 49   
     private AggregateProxyFactory aggregateProxyFactory = new DefaultAggregateProxyFactory();
 50   
 
 51   
     public static class Default extends DefaultPicoContainer {
 52  12
         public Default() {
 53  12
             super(new DefaultComponentFactory());
 54   
         }
 55   
     }
 56   
 
 57  72
     public DefaultPicoContainer(ComponentFactory componentFactory) {
 58  72
         if (componentFactory == null) {
 59  1
             throw new NullPointerException("componentFactory cannot be null");
 60   
         }
 61  71
         this.componentFactory = componentFactory;
 62   
     }
 63   
 
 64  5
     public final Object[] getComponents() {
 65  5
         Class[] componentTypes = getComponentTypes();
 66  5
         Object[] components = new Object[componentTypes.length];
 67  5
         for (int i = 0; i < componentTypes.length; i++) {
 68  8
             Class componentType = componentTypes[i];
 69  8
             components[i] = getComponent(componentType);
 70   
         }
 71  5
         return components;
 72   
     }
 73   
 
 74   
     /**
 75   
      * Shorthand for {@link #getAggregateComponentProxy(boolean, boolean)}(true, true).
 76   
      * @return a proxy.
 77   
      */
 78  4
     public Object getAggregateComponentProxy() {
 79  4
         return getAggregateComponentProxy(true, false);
 80   
     }
 81   
 
 82   
     /**
 83   
      * Returns a proxy that implements the union of all the components'
 84   
      * interfaces.
 85   
      * Calling a method on the returned Object will call the
 86   
      * method on all components in the container that implement
 87   
      * that interface.
 88   
      *
 89   
      * @param callInInstantiationOrder whether to call the methods in the order of instantiation (true) or reverse (false)
 90   
      * @param callInInstantiationOrder whether to exclude components registered with {@link #registerComponent(Class, Object)}
 91   
      * or {@link #registerComponent(Object)}
 92   
      */
 93  31
     public Object getAggregateComponentProxy(boolean callInInstantiationOrder, boolean callUnmanagedComponents) {
 94  31
         List aggregateComponents = new ArrayList(orderedComponents);
 95  31
         if(!callUnmanagedComponents) {
 96  29
             for (Iterator iterator = unmanagedComponents.iterator(); iterator.hasNext();) {
 97  2
                 aggregateComponents.remove( iterator.next() );
 98   
             }
 99   
         }
 100  31
         return aggregateProxyFactory.createAggregateProxy(
 101   
                 getClass().getClassLoader(),
 102   
                 aggregateComponents,
 103   
                 callInInstantiationOrder
 104   
         );
 105   
     }
 106   
 
 107   
 
 108  87
     public void registerComponent(Class componentType, Class componentImplementation) throws DuplicateComponentTypeRegistrationException, AssignabilityRegistrationException, NotConcreteRegistrationException, PicoIntrospectionException {
 109  87
         checkConcrete(componentImplementation);
 110   
 
 111  86
         Parameter[] parameters = new Parameter[componentFactory.getDependencies(componentImplementation).length];
 112  85
         for (int i = 0; i < parameters.length; i++) {
 113  54
             parameters[i] = createDefaultParameter();
 114   
         }
 115   
 
 116  85
         registerComponent(componentType, componentImplementation, parameters);
 117   
     }
 118   
 
 119  86
     public void registerComponent(Class componentType, Class componentImplementation, Parameter[] parameters) throws NotConcreteRegistrationException, AssignabilityRegistrationException, DuplicateComponentTypeRegistrationException {
 120  86
         checkConcrete(componentImplementation);
 121  86
         checkTypeCompatibility(componentType, componentImplementation);
 122  85
         checkTypeDuplication(componentType);
 123   
 
 124  84
         ComponentSpecification compSpec = new ComponentSpecification(componentFactory, componentType, componentImplementation, parameters);
 125  84
         componentToSpec.put(componentImplementation, compSpec);
 126  84
         registeredComponents.add(compSpec);
 127   
     }
 128   
 
 129  54
     protected Parameter createDefaultParameter() {
 130  54
         return new ComponentParameter();
 131   
     }
 132   
 
 133  92
     private void checkTypeDuplication(Class componentType) throws DuplicateComponentTypeRegistrationException {
 134  92
         for (Iterator iterator = registeredComponents.iterator(); iterator.hasNext();) {
 135  49
             Class aClass = ((ComponentSpecification) iterator.next()).getComponentType();
 136  49
             if (aClass == componentType) {
 137  2
                 throw new DuplicateComponentTypeRegistrationException(aClass);
 138   
             }
 139   
         }
 140   
     }
 141   
 
 142  94
     private void checkTypeCompatibility(Class componentType, Class componentImplementation) throws AssignabilityRegistrationException {
 143  94
         if (!componentType.isAssignableFrom(componentImplementation)) {
 144  2
             throw new AssignabilityRegistrationException(componentType, componentImplementation);
 145   
         }
 146   
     }
 147   
 
 148  173
     private void checkConcrete(Class componentImplementation) throws NotConcreteRegistrationException {
 149   
         // Assert that the component class is concrete.
 150  173
         boolean isAbstract = (componentImplementation.getModifiers() & Modifier.ABSTRACT) == Modifier.ABSTRACT;
 151  173
         if (componentImplementation.isInterface() || isAbstract) {
 152  1
             throw new NotConcreteRegistrationException(componentImplementation);
 153   
         }
 154   
     }
 155   
 
 156  1
     public void registerComponent(Object component) throws PicoRegistrationException {
 157  1
         registerComponent(component.getClass(), component);
 158   
     }
 159   
 
 160  8
     public void registerComponent(Class componentType, Object component) throws PicoRegistrationException {
 161  8
         checkTypeCompatibility(componentType, component.getClass());
 162  7
         checkTypeDuplication(componentType);
 163   
         //checkImplementationDuplication(component.getClass());
 164  6
         componentTypeToInstanceMap.put(componentType, component);
 165  6
         orderedComponents.add(component);
 166  6
         unmanagedComponents.add(component);
 167   
     }
 168   
 
 169  7
     public void addParameterToComponent(Class componentType, Class parameter, Object arg) throws PicoIntrospectionException {
 170  7
         ComponentSpecification componentSpec = ((ComponentSpecification) componentToSpec.get(componentType));
 171  7
         componentSpec.addConstantParameterBasedOnType(componentType, parameter, arg);
 172   
     }
 173   
 
 174  72
     public void registerComponent(Class componentImplementation) throws DuplicateComponentTypeRegistrationException, AssignabilityRegistrationException, NotConcreteRegistrationException, PicoIntrospectionException {
 175  72
         registerComponent(componentImplementation, componentImplementation);
 176   
     }
 177   
 
 178  38
     public void instantiateComponents() throws PicoInstantiationException, PicoInvocationTargetInitializationException, PicoIntrospectionException {
 179  38
         if (initialized == false) {
 180  37
             initializeComponents();
 181  33
             initialized = true;
 182   
         } else {
 183  1
             throw new IllegalStateException("PicoContainer Started Already");
 184   
         }
 185   
     }
 186   
 
 187   
     // This is Lazy and NOT public :-)
 188  37
     private void initializeComponents() throws PicoInstantiationException, PicoIntrospectionException {
 189  37
         for (Iterator iterator = registeredComponents.iterator(); iterator.hasNext();) {
 190  69
             ComponentSpecification componentSpec = (ComponentSpecification) iterator.next();
 191  69
             createComponent(componentSpec);
 192   
         }
 193   
     }
 194   
 
 195  85
     private Object createComponent(ComponentSpecification componentSpecification) throws PicoInstantiationException, PicoIntrospectionException {
 196  85
         if (!componentTypeToInstanceMap.containsKey(componentSpecification.getComponentType())) {
 197   
 
 198  70
             Object component = null;
 199   
 
 200   
             // reuse implementation if appropriate
 201  70
             Set compEntries = componentTypeToInstanceMap.entrySet();
 202  70
             for (Iterator iterator = compEntries.iterator();
 203  109
                  iterator.hasNext();) {
 204  40
                 Map.Entry entry = (Map.Entry) iterator.next();
 205  40
                 Object exisitingComp = entry.getValue();
 206  40
                 if (exisitingComp.getClass() == componentSpecification.getComponentImplementation()) {
 207  1
                     component = exisitingComp;
 208   
                     // We can exit now.
 209  1
                     break;
 210   
                 }
 211   
             }
 212   
 
 213   
             // create it if it was not reused
 214  70
             if (component == null) {
 215  69
                 component = componentSpecification.instantiateComponent(this);
 216  65
                 orderedComponents.add(component);
 217   
             }
 218   
 
 219  66
             componentTypeToInstanceMap.put(componentSpecification.getComponentType(), component);
 220   
 
 221  66
             return component;
 222   
         } else {
 223  15
             return componentTypeToInstanceMap.get(componentSpecification.getComponentType());
 224   
         }
 225   
     }
 226   
 
 227  94
     public Object getComponent(Class componentType) {
 228  94
         return componentTypeToInstanceMap.get(componentType);
 229   
     }
 230   
 
 231  46
     Object createComponent(Class componentType) throws PicoInstantiationException, PicoIntrospectionException {
 232  46
         Object componentInstance = getComponent(componentType);
 233   
 
 234  46
         if (componentInstance != null) {
 235  26
             return componentInstance;
 236   
         }
 237   
 
 238  20
         componentInstance = findSatisfyingComponent(componentType);
 239   
 
 240  19
         if (componentInstance != null) {
 241  1
             return componentInstance;
 242   
         }
 243   
 
 244   
         // try to find components that satisfy the interface (implements the component service asked for)
 245  18
         ComponentSpecification componentSpecification = findComponentSpecification(componentType);
 246  17
         if (componentSpecification == null) {
 247  1
             return null;
 248   
         }
 249   
 
 250  16
         componentType = componentSpecification.getComponentType();
 251   
 
 252   
         // if the component does not exist yet, instantiate it lazily
 253  16
         componentInstance = createComponent(componentSpecification);
 254   
 
 255  16
         return componentInstance;
 256   
     }
 257   
 
 258  20
     private Object findSatisfyingComponent(Class componentType) throws AmbiguousComponentResolutionException {
 259  20
         List found = new ArrayList();
 260   
 
 261  20
         for (Iterator iterator = componentTypeToInstanceMap.entrySet().iterator(); iterator.hasNext();) {
 262  5
             Map.Entry entry = (Map.Entry) iterator.next();
 263  5
             Class candidateType = (Class) entry.getKey();
 264  5
             if(componentType.isAssignableFrom(candidateType)) {
 265  3
                 found.add(candidateType);
 266   
             }
 267   
         }
 268   
 
 269  20
         if (found.size() > 1) {
 270  1
             Class[] ambiguousClasses = (Class[]) found.toArray(new Class[found.size()]);
 271  1
             throw new AmbiguousComponentResolutionException(ambiguousClasses);
 272   
         }
 273   
 
 274  19
         return found.isEmpty() ? null : componentTypeToInstanceMap.get(found.get(0));
 275   
     }
 276   
 
 277  21
     ComponentSpecification findComponentSpecification(Class componentType) throws AmbiguousComponentResolutionException {
 278  21
         List found = new ArrayList();
 279  21
         for (Iterator iterator = registeredComponents.iterator(); iterator.hasNext();) {
 280  44
             ComponentSpecification componentSpecification = (ComponentSpecification) iterator.next();
 281   
 
 282  44
             if (componentType.isAssignableFrom(componentSpecification.getComponentType())) {
 283  20
                 found.add(componentSpecification);
 284   
             }
 285   
         }
 286   
 
 287  21
         if (found.size() > 1) {
 288  1
             Class[] ambiguousClass = new Class[found.size()];
 289  1
             for (int i = 0; i < ambiguousClass.length; i++) {
 290  2
                 ambiguousClass[i] = ((ComponentSpecification) found.get(i)).getComponentImplementation();
 291   
             }
 292  1
             throw new AmbiguousComponentResolutionException(ambiguousClass);
 293   
         }
 294   
 
 295  20
         return found.isEmpty() ? null : ((ComponentSpecification) found.get(0));
 296   
     }
 297   
 
 298  4
     public Class[] getComponentTypes() {
 299   
         // Get my own
 300  4
         Set types = componentTypeToInstanceMap.keySet();
 301  4
         return (Class[]) types.toArray(new Class[types.size()]);
 302   
     }
 303   
 
 304  17
     public final boolean hasComponent(Class componentType) {
 305  17
         return getComponent(componentType) != null;
 306   
     }
 307   
 }
 308