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