Clover coverage report - PicoContainer - 1.0-beta-1
Coverage timestamp: Thu Aug 14 2003 23:16:27 BST
file stats: LOC: 246   Methods: 24
NCLOC: 151   Classes: 4
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 (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   
  * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant   *
 9   
  *****************************************************************************/
 10   
 
 11   
 package org.picocontainer.defaults;
 12   
 
 13   
 import org.picocontainer.internals.ComponentFactory;
 14   
 import org.picocontainer.internals.ComponentRegistry;
 15   
 import org.picocontainer.internals.Parameter;
 16   
 import org.picocontainer.PicoInitializationException;
 17   
 import org.picocontainer.PicoIntrospectionException;
 18   
 import org.picocontainer.PicoRegistrationException;
 19   
 import org.picocontainer.RegistrationPicoContainer;
 20   
 import org.picocontainer.extras.CompositeProxyFactory;
 21   
 import org.picocontainer.internals.ComponentSpecification;
 22   
 
 23   
 import java.io.Serializable;
 24   
 import java.lang.reflect.Modifier;
 25   
 import java.util.ArrayList;
 26   
 import java.util.Iterator;
 27   
 import java.util.List;
 28   
 import java.util.Set;
 29   
 import java.util.Collection;
 30   
 
 31   
 
 32   
 /**
 33   
  * Abstract baseclass for various PicoContainer implementations.
 34   
  *
 35   
  * @author Aslak Hellesoy
 36   
  * @version $Revision: 1.8 $
 37   
  */
 38   
 public class DefaultPicoContainer implements RegistrationPicoContainer, Serializable {
 39   
 
 40   
     private final ComponentRegistry componentRegistry;
 41   
     private final ComponentFactory componentFactory;
 42   
 
 43   
     // Keeps track of unmanaged components - components instantiated outside this internals
 44   
     protected List unmanagedComponents = new ArrayList();
 45   
 
 46   
     private boolean initialized;
 47   
     private CompositeProxyFactory compositeProxyFactory = new DefaultCompositeProxyFactory();
 48   
 
 49   
     public static class Default extends DefaultPicoContainer {
 50  74
         public Default() {
 51  74
             super(new DefaultComponentFactory(), new DefaultComponentRegistry());
 52   
         }
 53   
     }
 54   
 
 55   
     public static class WithComponentFactory extends DefaultPicoContainer {
 56  4
         public WithComponentFactory(ComponentFactory componentFactory) {
 57  4
             super(componentFactory, new DefaultComponentRegistry());
 58   
         }
 59   
     }
 60   
 
 61   
     public static class WithComponentRegistry extends DefaultPicoContainer {
 62  15
         public WithComponentRegistry(ComponentRegistry componentRegistry) {
 63  15
             super(new DefaultComponentFactory(), componentRegistry);
 64   
         }
 65   
     }
 66   
 
 67  96
     public DefaultPicoContainer(ComponentFactory componentFactory, ComponentRegistry componentRegistry) {
 68  96
         if (componentFactory == null) {
 69  1
             throw new NullPointerException("componentFactory cannot be null");
 70   
         }
 71  95
         if (componentRegistry == null) {
 72  1
             throw new NullPointerException("childRegistry cannot be null");
 73   
         }
 74  94
         this.componentFactory = componentFactory;
 75  94
         this.componentRegistry = componentRegistry;
 76   
     }
 77   
 
 78   
     // see PicoContainer interface for Javadocs
 79  5
     public final Object getComponentMulticaster() {
 80  5
         return getComponentMulticaster(true, false);
 81   
     }
 82   
 
 83   
     // see PicoContainer interface for Javadocs
 84  56
     public final Object getComponentMulticaster(boolean callInInstantiationOrder, boolean callUnmanagedComponents) {
 85  56
         List aggregateComponents = componentRegistry.getOrderedComponents();
 86  56
         if (!callUnmanagedComponents) {
 87  54
             for (Iterator iterator = unmanagedComponents.iterator(); iterator.hasNext();) {
 88  3
                 aggregateComponents.remove(iterator.next());
 89   
             }
 90   
         }
 91  56
         return compositeProxyFactory.createCompositeProxy(
 92   
                 getClass().getClassLoader(),
 93   
                 aggregateComponents,
 94   
                 callInInstantiationOrder
 95   
         );
 96   
     }
 97   
 
 98  152
     public void registerComponent(Object componentKey, Class componentImplementation) throws DuplicateComponentKeyRegistrationException, AssignabilityRegistrationException, NotConcreteRegistrationException, PicoIntrospectionException {
 99  152
         checkConcrete(componentImplementation);
 100  151
         checkTypeCompatibility(componentKey, componentImplementation);
 101  150
         checkKeyDuplication(componentKey);
 102   
 
 103  147
         registerComponent(new ComponentSpecification(componentFactory, componentKey, componentImplementation));
 104   
     }
 105   
 
 106  3
     public void registerComponent(Object componentKey, Class componentImplementation, Parameter[] parameters) throws NotConcreteRegistrationException, AssignabilityRegistrationException, DuplicateComponentKeyRegistrationException {
 107  3
         checkConcrete(componentImplementation);
 108  3
         checkTypeCompatibility(componentKey, componentImplementation);
 109  3
         checkKeyDuplication(componentImplementation);
 110   
 
 111  3
         registerComponent(new ComponentSpecification(componentFactory, componentKey, componentImplementation, parameters));
 112   
     }
 113   
 
 114  170
     private void registerComponent(ComponentSpecification compSpec) {
 115  170
         componentRegistry.registerComponent(compSpec);
 116   
     }
 117   
 
 118  175
     private void checkKeyDuplication(Object componentKey) throws DuplicateComponentKeyRegistrationException {
 119  175
         for (Iterator iterator = componentRegistry.getComponentSpecifications().iterator(); iterator.hasNext();) {
 120  118
             Object key = ((ComponentSpecification) iterator.next()).getComponentKey();
 121  118
             if (key == componentKey) {
 122  4
                 throw new DuplicateComponentKeyRegistrationException(key);
 123   
             }
 124   
         }
 125   
     }
 126   
 
 127  177
     private void checkTypeCompatibility(Object componentKey, Class componentImplementation) throws AssignabilityRegistrationException {
 128  177
         if (componentKey instanceof Class) {
 129  144
             Class componentType = (Class) componentKey;
 130  144
             if (!componentType.isAssignableFrom(componentImplementation)) {
 131  2
                 throw new AssignabilityRegistrationException(componentType, componentImplementation);
 132   
             }
 133   
         }
 134   
     }
 135   
 
 136  155
     private void checkConcrete(Class componentImplementation) throws NotConcreteRegistrationException {
 137   
         // Assert that the component class is concrete.
 138  155
         boolean isAbstract = (componentImplementation.getModifiers() & Modifier.ABSTRACT) == Modifier.ABSTRACT;
 139  155
         if (componentImplementation.isInterface() || isAbstract) {
 140  1
             throw new NotConcreteRegistrationException(componentImplementation);
 141   
         }
 142   
     }
 143   
 
 144  1
     public void registerComponentByInstance(Object component) throws PicoRegistrationException, PicoIntrospectionException {
 145  1
         registerComponent(component.getClass(), component);
 146   
     }
 147   
 
 148  23
     public void registerComponent(Object componentKey, Object component) throws PicoRegistrationException, PicoIntrospectionException {
 149  23
         checkTypeCompatibility(componentKey, component.getClass());
 150  22
         checkKeyDuplication(componentKey);
 151  21
         registerComponent(new ComponentSpecification(defaultComponentFactory(), componentKey, component.getClass(), null));
 152  21
         componentRegistry.putComponent(componentKey, component);
 153   
 
 154  21
         componentRegistry.addOrderedComponent(component);
 155  21
         unmanagedComponents.add(component);
 156   
     }
 157   
 
 158  21
     private ComponentFactory defaultComponentFactory() {
 159  21
         return componentFactory;
 160   
     }
 161   
 
 162  7
     public void addParameterToComponent(Object componentKey, Class parameter, Object arg) throws PicoIntrospectionException {
 163  7
         ComponentSpecification componentSpec = componentRegistry.getComponentSpec(componentKey);
 164  7
         componentSpec.addConstantParameterBasedOnType(parameter, arg);
 165   
     }
 166   
 
 167  88
     public void registerComponentByClass(Class componentImplementation) throws DuplicateComponentKeyRegistrationException, AssignabilityRegistrationException, NotConcreteRegistrationException, PicoIntrospectionException {
 168  88
         registerComponent(componentImplementation, componentImplementation);
 169   
     }
 170   
 
 171   
     /**
 172   
      * TODO promote to RegistrationPicoContainer, it's all Pauls fault anyway
 173   
      * @param componentKey
 174   
      */
 175  4
     public void unregisterComponent(Object componentKey) {
 176  4
         componentRegistry.unregisterComponent(componentKey);
 177   
     }
 178   
 
 179  79
     public void instantiateComponents() throws PicoInitializationException, PicoInvocationTargetInitializationException {
 180  79
         if (initialized == false) {
 181  76
             initializeComponents();
 182  70
             initialized = true;
 183   
         } else {
 184  3
             throw new IllegalStateException("PicoContainer Started Already");
 185   
         }
 186   
     }
 187   
 
 188   
     // This is Lazy and NOT public :-)
 189  76
     private void initializeComponents() throws PicoInitializationException {
 190  76
         for (Iterator iterator = componentRegistry.getComponentSpecifications().iterator(); iterator.hasNext();) {
 191  145
             componentRegistry.createComponent((ComponentSpecification) iterator.next());
 192   
         }
 193   
     }
 194   
 
 195   
 
 196  98
     public Object getComponent(Object componentKey) {
 197  98
         return componentRegistry.getComponentInstance(componentKey);
 198   
     }
 199   
 
 200  16
     public Collection getComponents() {
 201   
         /* <ASLAK>
 202   
          * TODO: make final again
 203   
          *
 204   
          * There is a reason why we're not simply doing
 205   
          *
 206   
          * return componentKeyToInstanceMap.values().toArray();
 207   
          *
 208   
          * getComponents() and getComponentKeys() are tightly related.
 209   
          * They have a "contract" between each other. More specifically:
 210   
          *
 211   
          * 1) They should always return equally sized arrays.
 212   
          * 2) For each key returned by getComponentKeys() the call to getComponent(key)
 213   
          *    should never return null.
 214   
          *
 215   
          * If Java had supported DBC, we would have expressed this contract on the PicoContainer
 216   
          * interface itself, forcing that contract to be respected through the whole hierarchy.
 217   
          * Since this isn't possible in Java, we as programmers use other means (comments and final
 218   
          * being some of them) to "enforce" the contract to be respected.
 219   
          *
 220   
          * Overriding getComponents() and not getComponentType() has the potential danger in that
 221   
          * it might violate the contract. Making one of the methods final (that would naturally be
 222   
          * getComponents()) and finalising the contract in that final method prevents the contract
 223   
          * from being violated. Ever.
 224   
          *
 225   
          * Using final on methods is a way to avoid contracts being broken.
 226   
          *
 227   
          * Ideally, this method should be final, so we can avoid the contract being accidentally
 228   
          * broken.
 229   
          *
 230   
          * </ASLAK>
 231   
          */
 232   
 
 233  16
         return componentRegistry.getComponentInstances();
 234   
     }
 235   
 
 236   
     //TODO - remove from PicoContainer interface?
 237   
     //TODO - maybe not ?
 238  4
     public Collection getComponentKeys() {
 239  4
         return componentRegistry.getComponentInstanceKeys();
 240   
     }
 241   
 
 242  33
     public final boolean hasComponent(Object componentKey) {
 243  33
         return getComponent(componentKey) != null;
 244   
     }
 245   
 }
 246