KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jdon > container > pico > JdonPicoContainer


1 /*
2  * Copyright 2003-2006 the original author or authors.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  */

16 package com.jdon.container.pico;
17
18 import java.io.Serializable JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27
28 import org.picocontainer.ComponentAdapter;
29 import org.picocontainer.MutablePicoContainer;
30 import org.picocontainer.Parameter;
31 import org.picocontainer.PicoContainer;
32 import org.picocontainer.PicoException;
33 import org.picocontainer.PicoRegistrationException;
34 import org.picocontainer.PicoVerificationException;
35 import org.picocontainer.PicoVisitor;
36 import org.picocontainer.alternatives.ImmutablePicoContainer;
37 import org.picocontainer.defaults.AmbiguousComponentResolutionException;
38 import org.picocontainer.defaults.CachingComponentAdapter;
39 import org.picocontainer.defaults.CachingComponentAdapterFactory;
40 import org.picocontainer.defaults.ComponentAdapterFactory;
41 import org.picocontainer.defaults.ConstructorInjectionComponentAdapterFactory;
42 import org.picocontainer.defaults.DefaultComponentAdapterFactory;
43 import org.picocontainer.defaults.DefaultPicoContainer;
44 import org.picocontainer.defaults.DuplicateComponentKeyRegistrationException;
45 import org.picocontainer.defaults.InstanceComponentAdapter;
46 import org.picocontainer.defaults.LifecycleVisitor;
47 import org.picocontainer.defaults.VerifyingVisitor;
48
49 import com.jdon.util.Debug;
50
51 /**
52  * modify the method getComponentInstance of DefaultPicoContainer of picocontainer
53  *
54  * @author <a HREF="mailto:banqiao@jdon.com">banq</a>
55  *
56  */

57 public class JdonPicoContainer implements MutablePicoContainer, Serializable JavaDoc {
58     public final static String JavaDoc module = JdonPicoContainer.class.getName();
59   
60
61         private Map JavaDoc componentKeyToAdapterCache = new HashMap JavaDoc();
62         
63         private Map JavaDoc componentKeyToInstanceCache = new HashMap JavaDoc();
64         
65         private ComponentAdapterFactory componentAdapterFactory;
66         private PicoContainer parent;
67         private List JavaDoc componentAdapters = new ArrayList JavaDoc();
68
69         // Keeps track of instantiation order.
70
private List JavaDoc orderedComponentAdapters = new ArrayList JavaDoc();
71
72         private boolean started = false;
73         private boolean disposed = false;
74         private HashSet JavaDoc children = new HashSet JavaDoc();
75
76         /**
77          * Creates a new container with a custom ComponentAdapterFactory and a parent container.
78          * <p/>
79          * <em>
80          * Important note about caching: If you intend the components to be cached, you should pass
81          * in a factory that creates {@link CachingComponentAdapter} instances, such as for example
82          * {@link CachingComponentAdapterFactory}. CachingComponentAdapterFactory can delegate to
83          * other ComponentAdapterFactories.
84          * </em>
85          *
86          * @param componentAdapterFactory the factory to use for creation of ComponentAdapters.
87          * @param parent the parent container (used for component dependency lookups).
88          */

89         public JdonPicoContainer(ComponentAdapterFactory componentAdapterFactory, PicoContainer parent) {
90             if(componentAdapterFactory == null) throw new NullPointerException JavaDoc("componentAdapterFactory");
91             this.componentAdapterFactory = componentAdapterFactory;
92             this.parent = parent == null ? null : new ImmutablePicoContainer(parent);
93         }
94
95         /**
96          * Creates a new container with a (caching) {@link DefaultComponentAdapterFactory}
97          * and a parent container.
98          */

99         public JdonPicoContainer(PicoContainer parent) {
100             this(new DefaultComponentAdapterFactory(), parent);
101         }
102
103         /**
104          * Creates a new container with a custom ComponentAdapterFactory and no parent container.
105          *
106          * @param componentAdapterFactory the ComponentAdapterFactory to use.
107          */

108         public JdonPicoContainer(ComponentAdapterFactory componentAdapterFactory) {
109             this(componentAdapterFactory, null);
110         }
111
112         /**
113          * Creates a new container with a (caching) {@link DefaultComponentAdapterFactory} and no parent container.
114          */

115         public JdonPicoContainer() {
116             this(new DefaultComponentAdapterFactory(), null);
117         }
118
119         public Collection JavaDoc getComponentAdapters() {
120             return Collections.unmodifiableList(componentAdapters);
121         }
122
123         public final ComponentAdapter getComponentAdapter(Object JavaDoc componentKey) throws AmbiguousComponentResolutionException {
124             ComponentAdapter adapter = (ComponentAdapter) componentKeyToAdapterCache.get(componentKey);
125             if (adapter == null && parent != null) {
126                 adapter = parent.getComponentAdapter(componentKey);
127             }
128             return adapter;
129         }
130
131         public ComponentAdapter getComponentAdapterOfType(Class JavaDoc componentType) {
132             // See http://jira.codehaus.org/secure/ViewIssue.jspa?key=PICO-115
133
ComponentAdapter adapterByKey = getComponentAdapter(componentType);
134             if (adapterByKey != null) {
135                 return adapterByKey;
136             }
137
138             List JavaDoc found = getComponentAdaptersOfType(componentType);
139
140             if (found.size() == 1) {
141                 return ((ComponentAdapter) found.get(0));
142             } else if (found.size() == 0) {
143                 if (parent != null) {
144                     return parent.getComponentAdapterOfType(componentType);
145                 } else {
146                     return null;
147                 }
148             } else {
149                 Class JavaDoc[] foundClasses = new Class JavaDoc[found.size()];
150                 for (int i = 0; i < foundClasses.length; i++) {
151                     ComponentAdapter componentAdapter = (ComponentAdapter) found.get(i);
152                     foundClasses[i] = componentAdapter.getComponentImplementation();
153                 }
154
155                 throw new AmbiguousComponentResolutionException(componentType, foundClasses);
156             }
157         }
158
159         public List JavaDoc getComponentAdaptersOfType(Class JavaDoc componentType) {
160             if(componentType == null) {
161                 return Collections.EMPTY_LIST;
162             }
163             List JavaDoc found = new ArrayList JavaDoc();
164             for (Iterator JavaDoc iterator = getComponentAdapters().iterator(); iterator.hasNext();) {
165                 ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next();
166
167                 if (componentType.isAssignableFrom(componentAdapter.getComponentImplementation())) {
168                     found.add(componentAdapter);
169                 }
170             }
171             return found;
172         }
173
174         /**
175          * {@inheritDoc}
176          * This method can be used to override the ComponentAdapter created by the {@link ComponentAdapterFactory}
177          * passed to the constructor of this container.
178          */

179         public ComponentAdapter registerComponent(ComponentAdapter componentAdapter) throws DuplicateComponentKeyRegistrationException {
180             Object JavaDoc componentKey = componentAdapter.getComponentKey();
181             if (componentKeyToAdapterCache.containsKey(componentKey)) {
182                 throw new DuplicateComponentKeyRegistrationException(componentKey);
183             }
184             componentAdapters.add(componentAdapter);
185             componentKeyToAdapterCache.put(componentKey, componentAdapter);
186             return componentAdapter;
187         }
188
189         public ComponentAdapter unregisterComponent(Object JavaDoc componentKey) {
190             ComponentAdapter adapter = (ComponentAdapter) componentKeyToAdapterCache.remove(componentKey);
191             componentAdapters.remove(adapter);
192             orderedComponentAdapters.remove(adapter);
193             return adapter;
194         }
195
196         /**
197          * {@inheritDoc}
198          * The returned ComponentAdapter will be an {@link InstanceComponentAdapter}.
199          */

200         public ComponentAdapter registerComponentInstance(Object JavaDoc component) throws PicoRegistrationException {
201             return registerComponentInstance(component.getClass(), component);
202         }
203
204         /**
205          * {@inheritDoc}
206          * The returned ComponentAdapter will be an {@link InstanceComponentAdapter}.
207          */

208         public ComponentAdapter registerComponentInstance(Object JavaDoc componentKey, Object JavaDoc componentInstance) throws PicoRegistrationException {
209             if (componentInstance instanceof MutablePicoContainer) {
210                 MutablePicoContainer pc = (MutablePicoContainer) componentInstance;
211                 Object JavaDoc contrivedKey = new Object JavaDoc();
212                 String JavaDoc contrivedComp = "";
213                 pc.registerComponentInstance(contrivedKey, contrivedComp);
214                 try {
215                     if (this.getComponentInstance(contrivedKey) != null) {
216                         throw new PicoRegistrationException("Cannot register a container to itself. The container is already implicitly registered.");
217                     }
218                 } finally {
219                     pc.unregisterComponent(contrivedKey);
220                 }
221
222             }
223             ComponentAdapter componentAdapter = new InstanceComponentAdapter(componentKey, componentInstance);
224             registerComponent(componentAdapter);
225             return componentAdapter;
226         }
227
228         /**
229          * {@inheritDoc}
230          * The returned ComponentAdapter will be instantiated by the {@link ComponentAdapterFactory}
231          * passed to the container's constructor.
232          */

233         public ComponentAdapter registerComponentImplementation(Class JavaDoc componentImplementation) throws PicoRegistrationException {
234             return registerComponentImplementation(componentImplementation, componentImplementation);
235         }
236
237         /**
238          * {@inheritDoc}
239          * The returned ComponentAdapter will be instantiated by the {@link ComponentAdapterFactory}
240          * passed to the container's constructor.
241          */

242         public ComponentAdapter registerComponentImplementation(Object JavaDoc componentKey, Class JavaDoc componentImplementation) throws PicoRegistrationException {
243             return registerComponentImplementation(componentKey, componentImplementation, (Parameter[]) null);
244         }
245
246         /**
247          * {@inheritDoc}
248          * The returned ComponentAdapter will be instantiated by the {@link ComponentAdapterFactory}
249          * passed to the container's constructor.
250          */

251         public ComponentAdapter registerComponentImplementation(Object JavaDoc componentKey, Class JavaDoc componentImplementation, Parameter[] parameters) throws PicoRegistrationException {
252             ComponentAdapter componentAdapter = componentAdapterFactory.createComponentAdapter(componentKey, componentImplementation, parameters);
253             registerComponent(componentAdapter);
254             return componentAdapter;
255         }
256
257         /**
258          * Same as {@link #registerComponentImplementation(java.lang.Object, java.lang.Class, org.picocontainer.Parameter[])}
259          * but with parameters as a {@link List}. Makes it possible to use with Groovy arrays (which are actually Lists).
260          */

261         public ComponentAdapter registerComponentImplementation(Object JavaDoc componentKey, Class JavaDoc componentImplementation, List JavaDoc parameters) throws PicoRegistrationException {
262             Parameter[] parametersAsArray = (Parameter[]) parameters.toArray(new Parameter[parameters.size()]);
263             return registerComponentImplementation(componentKey, componentImplementation, parametersAsArray);
264         }
265
266         private void addOrderedComponentAdapter(ComponentAdapter componentAdapter) {
267             if (!orderedComponentAdapters.contains(componentAdapter)) {
268                 orderedComponentAdapters.add(componentAdapter);
269             }
270         }
271
272         public List JavaDoc getComponentInstances() throws PicoException {
273             return getComponentInstancesOfType(Object JavaDoc.class);
274         }
275
276         public List JavaDoc getComponentInstancesOfType(Class JavaDoc componentType) throws PicoException {
277             if(componentType == null) {
278                 return Collections.EMPTY_LIST;
279             }
280
281             Map JavaDoc adapterToInstanceMap = new HashMap JavaDoc();
282             for (Iterator JavaDoc iterator = componentAdapters.iterator(); iterator.hasNext();) {
283                 ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next();
284                 if (componentType.isAssignableFrom(componentAdapter.getComponentImplementation())) {
285                     Object JavaDoc componentInstance = getInstance(componentAdapter);
286                     adapterToInstanceMap.put(componentAdapter, componentInstance);
287
288                     // This is to ensure all are added. (Indirect dependencies will be added
289
// from InstantiatingComponentAdapter).
290
addOrderedComponentAdapter(componentAdapter);
291                 }
292             }
293             List JavaDoc result = new ArrayList JavaDoc();
294             for (Iterator JavaDoc iterator = orderedComponentAdapters.iterator(); iterator.hasNext();) {
295                 Object JavaDoc componentAdapter = iterator.next();
296                 final Object JavaDoc componentInstance = adapterToInstanceMap.get(componentAdapter);
297                 if (componentInstance != null) {
298                     // may be null in the case of the "implicit" adapter
299
// representing "this".
300
result.add(componentInstance);
301                 }
302             }
303             return result;
304         }
305
306         public Object JavaDoc getComponentInstance(Object JavaDoc componentKey) throws PicoException {
307             ComponentAdapter componentAdapter = getComponentAdapter(componentKey);
308             if (componentAdapter != null) {
309                 return getInstance(componentAdapter);
310             } else {
311                 return null;
312             }
313         }
314
315         public Object JavaDoc getComponentInstanceOfType(Class JavaDoc componentType) {
316             final ComponentAdapter componentAdapter = getComponentAdapterOfType(componentType);
317             return componentAdapter == null ? null : getInstance(componentAdapter);
318         }
319
320         /**
321          * modify this method of old DefaultPicocontainer
322          * @param componentAdapter
323          * @return
324          */

325         public Object JavaDoc getInstance(ComponentAdapter componentAdapter) {
326             Object JavaDoc componentKey = componentAdapter.getComponentKey();
327             Object JavaDoc instance = componentKeyToInstanceCache.get(componentKey);
328             if (instance == null) {
329                 if (componentAdapter != null) {
330                     instance = getTrueInstance(componentAdapter);
331                     if (instance != null){
332                         componentKeyToInstanceCache.put(componentKey, instance);
333                     }
334                 }
335             }
336             return instance;
337         
338         }
339         
340         private Object JavaDoc getTrueInstance(ComponentAdapter componentAdapter) {
341       
342             // check wether this is our adapter
343
// we need to check this to ensure up-down dependencies cannot be followed
344
final boolean isLocal = componentAdapters.contains(componentAdapter);
345
346             if (isLocal) {
347                 Object JavaDoc instance = componentAdapter.getComponentInstance(this);
348
349                 addOrderedComponentAdapter(componentAdapter);
350
351                 return instance;
352             } else if (parent != null) {
353                 return parent.getComponentInstance(componentAdapter.getComponentKey());
354             }
355
356             // TODO: decide .. exception or null?
357
// exceptrion: mx: +1, joehni +1
358
return null;
359         }
360         
361
362
363         public PicoContainer getParent() {
364             return parent;
365         }
366
367         public ComponentAdapter unregisterComponentByInstance(Object JavaDoc componentInstance) {
368             Collection JavaDoc componentAdapters = getComponentAdapters();
369             for (Iterator JavaDoc iterator = componentAdapters.iterator(); iterator.hasNext();) {
370                 ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next();
371                 if (getInstance(componentAdapter).equals(componentInstance)) {
372                     return unregisterComponent(componentAdapter.getComponentKey());
373                 }
374             }
375             return null;
376         }
377
378         /**
379          * @deprecated since 1.1 - Use new VerifyingVisitor().traverse(this)
380         */

381         public void verify() throws PicoVerificationException {
382             new VerifyingVisitor().traverse(this);
383         }
384
385         /**
386          * Start the components of this PicoContainer and all its logical child containers.
387          * Any component implementing the lifecycle interface {@link org.picocontainer.Startable} will be started.
388          * @see #makeChildContainer()
389          * @see #addChildContainer(PicoContainer)
390          * @see #removeChildContainer(PicoContainer)
391          */

392         public void start() {
393             if (disposed) throw new IllegalStateException JavaDoc("Already disposed");
394             if (started) throw new IllegalStateException JavaDoc("Already started");
395             LifecycleVisitor.start(this);
396             started = true;
397         }
398
399         /**
400          * Stop the components of this PicoContainer and all its logical child containers.
401          * Any component implementing the lifecycle interface {@link org.picocontainer.Startable} will be stopped.
402          * @see #makeChildContainer()
403          * @see #addChildContainer(PicoContainer)
404          * @see #removeChildContainer(PicoContainer)
405          */

406         public void stop() {
407             if (disposed) throw new IllegalStateException JavaDoc("Already disposed");
408             if (!started) throw new IllegalStateException JavaDoc("Not started");
409             LifecycleVisitor.stop(this);
410             started = false;
411         }
412
413         /**
414          * Dispose the components of this PicoContainer and all its logical child containers.
415          * Any component implementing the lifecycle interface {@link org.picocontainer.Disposable} will be disposed.
416          * @see #makeChildContainer()
417          * @see #addChildContainer(PicoContainer)
418          * @see #removeChildContainer(PicoContainer)
419          */

420         public void dispose() {
421             if (disposed) throw new IllegalStateException JavaDoc("Already disposed");
422             LifecycleVisitor.dispose(this);
423             disposed = true;
424         }
425
426         public MutablePicoContainer makeChildContainer() {
427             DefaultPicoContainer pc = new DefaultPicoContainer(componentAdapterFactory, this);
428             addChildContainer(pc);
429             return pc;
430         }
431
432         public boolean addChildContainer(PicoContainer child) {
433             return children.add(child);
434         }
435
436         public boolean removeChildContainer(PicoContainer child) {
437             final boolean result = children.remove(child);
438             return result;
439         }
440
441         public void accept(PicoVisitor visitor) {
442             visitor.visitContainer(this);
443             final List JavaDoc componentAdapters = new ArrayList JavaDoc(getComponentAdapters());
444             for (Iterator JavaDoc iterator = componentAdapters.iterator(); iterator.hasNext();) {
445                 ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next();
446                 componentAdapter.accept(visitor);
447             }
448             final List JavaDoc allChildren = new ArrayList JavaDoc(children);
449             for (Iterator JavaDoc iterator = allChildren.iterator(); iterator.hasNext();) {
450                 PicoContainer child = (PicoContainer) iterator.next();
451                 child.accept(visitor);
452             }
453         }
454     }
Popular Tags