View Javadoc
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 public Default() { 51 super(new DefaultComponentFactory(), new DefaultComponentRegistry()); 52 } 53 } 54 55 public static class WithComponentFactory extends DefaultPicoContainer { 56 public WithComponentFactory(ComponentFactory componentFactory) { 57 super(componentFactory, new DefaultComponentRegistry()); 58 } 59 } 60 61 public static class WithComponentRegistry extends DefaultPicoContainer { 62 public WithComponentRegistry(ComponentRegistry componentRegistry) { 63 super(new DefaultComponentFactory(), componentRegistry); 64 } 65 } 66 67 public DefaultPicoContainer(ComponentFactory componentFactory, ComponentRegistry componentRegistry) { 68 if (componentFactory == null) { 69 throw new NullPointerException("componentFactory cannot be null"); 70 } 71 if (componentRegistry == null) { 72 throw new NullPointerException("childRegistry cannot be null"); 73 } 74 this.componentFactory = componentFactory; 75 this.componentRegistry = componentRegistry; 76 } 77 78 // see PicoContainer interface for Javadocs 79 public final Object getComponentMulticaster() { 80 return getComponentMulticaster(true, false); 81 } 82 83 // see PicoContainer interface for Javadocs 84 public final Object getComponentMulticaster(boolean callInInstantiationOrder, boolean callUnmanagedComponents) { 85 List aggregateComponents = componentRegistry.getOrderedComponents(); 86 if (!callUnmanagedComponents) { 87 for (Iterator iterator = unmanagedComponents.iterator(); iterator.hasNext();) { 88 aggregateComponents.remove(iterator.next()); 89 } 90 } 91 return compositeProxyFactory.createCompositeProxy( 92 getClass().getClassLoader(), 93 aggregateComponents, 94 callInInstantiationOrder 95 ); 96 } 97 98 public void registerComponent(Object componentKey, Class componentImplementation) throws DuplicateComponentKeyRegistrationException, AssignabilityRegistrationException, NotConcreteRegistrationException, PicoIntrospectionException { 99 checkConcrete(componentImplementation); 100 checkTypeCompatibility(componentKey, componentImplementation); 101 checkKeyDuplication(componentKey); 102 103 registerComponent(new ComponentSpecification(componentFactory, componentKey, componentImplementation)); 104 } 105 106 public void registerComponent(Object componentKey, Class componentImplementation, Parameter[] parameters) throws NotConcreteRegistrationException, AssignabilityRegistrationException, DuplicateComponentKeyRegistrationException { 107 checkConcrete(componentImplementation); 108 checkTypeCompatibility(componentKey, componentImplementation); 109 checkKeyDuplication(componentImplementation); 110 111 registerComponent(new ComponentSpecification(componentFactory, componentKey, componentImplementation, parameters)); 112 } 113 114 private void registerComponent(ComponentSpecification compSpec) { 115 componentRegistry.registerComponent(compSpec); 116 } 117 118 private void checkKeyDuplication(Object componentKey) throws DuplicateComponentKeyRegistrationException { 119 for (Iterator iterator = componentRegistry.getComponentSpecifications().iterator(); iterator.hasNext();) { 120 Object key = ((ComponentSpecification) iterator.next()).getComponentKey(); 121 if (key == componentKey) { 122 throw new DuplicateComponentKeyRegistrationException(key); 123 } 124 } 125 } 126 127 private void checkTypeCompatibility(Object componentKey, Class componentImplementation) throws AssignabilityRegistrationException { 128 if (componentKey instanceof Class) { 129 Class componentType = (Class) componentKey; 130 if (!componentType.isAssignableFrom(componentImplementation)) { 131 throw new AssignabilityRegistrationException(componentType, componentImplementation); 132 } 133 } 134 } 135 136 private void checkConcrete(Class componentImplementation) throws NotConcreteRegistrationException { 137 // Assert that the component class is concrete. 138 boolean isAbstract = (componentImplementation.getModifiers() & Modifier.ABSTRACT) == Modifier.ABSTRACT; 139 if (componentImplementation.isInterface() || isAbstract) { 140 throw new NotConcreteRegistrationException(componentImplementation); 141 } 142 } 143 144 public void registerComponentByInstance(Object component) throws PicoRegistrationException, PicoIntrospectionException { 145 registerComponent(component.getClass(), component); 146 } 147 148 public void registerComponent(Object componentKey, Object component) throws PicoRegistrationException, PicoIntrospectionException { 149 checkTypeCompatibility(componentKey, component.getClass()); 150 checkKeyDuplication(componentKey); 151 registerComponent(new ComponentSpecification(defaultComponentFactory(), componentKey, component.getClass(), null)); 152 componentRegistry.putComponent(componentKey, component); 153 154 componentRegistry.addOrderedComponent(component); 155 unmanagedComponents.add(component); 156 } 157 158 private ComponentFactory defaultComponentFactory() { 159 return componentFactory; 160 } 161 162 public void addParameterToComponent(Object componentKey, Class parameter, Object arg) throws PicoIntrospectionException { 163 ComponentSpecification componentSpec = componentRegistry.getComponentSpec(componentKey); 164 componentSpec.addConstantParameterBasedOnType(parameter, arg); 165 } 166 167 public void registerComponentByClass(Class componentImplementation) throws DuplicateComponentKeyRegistrationException, AssignabilityRegistrationException, NotConcreteRegistrationException, PicoIntrospectionException { 168 registerComponent(componentImplementation, componentImplementation); 169 } 170 171 /*** 172 * TODO promote to RegistrationPicoContainer, it's all Pauls fault anyway 173 * @param componentKey 174 */ 175 public void unregisterComponent(Object componentKey) { 176 componentRegistry.unregisterComponent(componentKey); 177 } 178 179 public void instantiateComponents() throws PicoInitializationException, PicoInvocationTargetInitializationException { 180 if (initialized == false) { 181 initializeComponents(); 182 initialized = true; 183 } else { 184 throw new IllegalStateException("PicoContainer Started Already"); 185 } 186 } 187 188 // This is Lazy and NOT public :-) 189 private void initializeComponents() throws PicoInitializationException { 190 for (Iterator iterator = componentRegistry.getComponentSpecifications().iterator(); iterator.hasNext();) { 191 componentRegistry.createComponent((ComponentSpecification) iterator.next()); 192 } 193 } 194 195 196 public Object getComponent(Object componentKey) { 197 return componentRegistry.getComponentInstance(componentKey); 198 } 199 200 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 return componentRegistry.getComponentInstances(); 234 } 235 236 //TODO - remove from PicoContainer interface? 237 //TODO - maybe not ? 238 public Collection getComponentKeys() { 239 return componentRegistry.getComponentInstanceKeys(); 240 } 241 242 public final boolean hasComponent(Object componentKey) { 243 return getComponent(componentKey) != null; 244 } 245 }

This page was automatically generated by Maven