001 /*****************************************************************************
002 * Copyright (C) PicoContainer Organization. All rights reserved. *
003 * ------------------------------------------------------------------------- *
004 * The software in this package is published under the terms of the BSD *
005 * style license a copy of which has been included with this distribution in *
006 * the LICENSE.txt file. *
007 * *
008 * Original Code By Centerline Computers, Inc. *
009 *****************************************************************************/
010
011 package org.picocontainer.gems.containers;
012
013 import org.picocontainer.ComponentAdapter;
014 import org.picocontainer.MutablePicoContainer;
015 import org.picocontainer.Parameter;
016 import org.picocontainer.PicoContainer;
017 import org.picocontainer.PicoVisitor;
018 import org.picocontainer.NameBinding;
019 import org.picocontainer.lifecycle.LifecycleState;
020
021 import java.io.ObjectInputStream;
022 import java.io.ObjectOutputStream;
023 import java.io.Serializable;
024 import java.util.Collection;
025 import java.util.List;
026 import java.util.Properties;
027 import java.lang.annotation.Annotation;
028 import java.lang.reflect.Type;
029
030 import org.apache.log4j.Logger;
031
032 /**
033 * Decorates a MutablePicoContainer to provide extensive tracing capabilities
034 * for all function calls into the Picocontainers.
035 * <p>
036 * By default, this class uses <tt>org.picocontainer.PicoContainer</tt> as its
037 * logging category, however, this may be changed by providing the logger in its
038 * alternate constructor.
039 * </p>
040 * <p>
041 * Start and Stop events are logged under <tt>info</tt> priority, as are all
042 * conditions where querying for an object returns a null object (e.g.,
043 * getComponentAdapter(Object) returns null). All other functions use
044 * <tt>debug</tt> priority.
045 * </p>
046 * <p>
047 * If used in nanocontainer, you can add wrap your PicoContainer with the
048 * Log4jTracingContainerDecorator: (Groovy Example)
049 * </p>
050 *
051 * <pre>
052 * pico = builder.container(parent: parent) {
053 * //addComponent(.....)
054 * //And others.
055 * }
056 *
057 * //Wrap the underlying NanoContainer with a Decorated Pico.
058 * pico = new org.picocontainer.gems.containers.Log4jTracingContainerDecorator (pico.getPico())
059 * </pre>
060 *
061 * @author Michael Rimov
062 * @deprecated Since PicoContainer 2.3, Pico 2 ComponentAdapters can now do everything that this
063 * decorator provided.
064 */
065 @Deprecated
066 @SuppressWarnings("serial")
067 public class Log4jTracingContainerDecorator implements MutablePicoContainer, Serializable {
068
069
070 /** Wrapped container. */
071 private final MutablePicoContainer delegate;
072
073 /** Logger instance used for writing events. */
074 private transient Logger logger;
075
076 /**
077 * Default typical wrapper that wraps another MutablePicoContainer.
078 *
079 * @param delegate Container to be decorated.
080 *
081 * @throws NullPointerException if delegate is null.
082 */
083 public Log4jTracingContainerDecorator(final MutablePicoContainer delegate) {
084 this(delegate, Logger.getLogger(PicoContainer.class));
085 }
086
087 /**
088 * Alternate constructor that allows specification of the Logger to use.
089 *
090 * @param delegate Container to be decorated.
091 * @param logger specific Log4j Logger to use.
092 *
093 * @throws NullPointerException if delegate or logger is null.
094 */
095 public Log4jTracingContainerDecorator(final MutablePicoContainer delegate, final Logger logger) {
096 if (delegate == null) {
097 throw new NullPointerException("delegate");
098 }
099
100 if (logger == null) {
101 throw new NullPointerException("logger");
102 }
103
104 this.delegate = delegate;
105 this.logger = logger;
106 }
107
108 /**
109 * Standard message handling for cases when a null object is returned for a
110 * given key.
111 *
112 * @param componentKeyOrType Component key that does not exist
113 * @param target Logger to log into
114 */
115 protected void onKeyOrTypeDoesNotExistInContainer(final Object componentKeyOrType, final Logger target) {
116 String s =
117 componentKeyOrType instanceof Class ? ((Class)componentKeyOrType).getName() : (String)componentKeyOrType;
118 logger.info("Could not find component " + s
119 + " in container or parent container.");
120 }
121
122 /**
123 * {@inheritDoc}
124 *
125 * @param visitor
126 *
127 * @see org.picocontainer.PicoContainer#accept(org.picocontainer.PicoVisitor)
128 */
129 public void accept(final PicoVisitor visitor) {
130 if (logger.isDebugEnabled()) {
131 logger.debug("Visiting Container " + delegate + " with visitor " + visitor);
132 }
133 delegate.accept(visitor);
134 }
135
136 /**
137 * {@inheritDoc}
138 *
139 * @param child
140 *
141 * @return
142 *
143 * @see org.picocontainer.MutablePicoContainer#addChildContainer(org.picocontainer.PicoContainer)
144 */
145 public MutablePicoContainer addChildContainer(final PicoContainer child) {
146 if (logger.isDebugEnabled()) {
147 logger.debug("Adding child container: " + child + " to container " + delegate);
148 }
149 return delegate.addChildContainer(child);
150 }
151
152 /**
153 * {@inheritDoc}
154 *
155 * @see org.picocontainer.Disposable#dispose()
156 */
157 public void dispose() {
158 if (logger.isDebugEnabled()) {
159 logger.debug("Disposing container " + delegate);
160 }
161 delegate.dispose();
162 }
163
164 /**
165 * {@inheritDoc}
166 *
167 * @param componentKey
168 *
169 * @return
170 *
171 * @see org.picocontainer.PicoContainer#getComponentAdapter(java.lang.Object)
172 */
173 public ComponentAdapter<?> getComponentAdapter(final Object componentKey) {
174 if (logger.isDebugEnabled()) {
175 logger.debug("Locating component adapter with key " + componentKey);
176 }
177
178 ComponentAdapter adapter = delegate.getComponentAdapter(componentKey);
179 if (adapter == null) {
180 onKeyOrTypeDoesNotExistInContainer(componentKey, logger);
181 }
182 return adapter;
183 }
184
185 /**
186 * {@inheritDoc}
187 *
188 * @param componentType
189 *
190 * @return ComponentAdapter or null.
191 *
192 * @see org.picocontainer.PicoContainer#getComponentAdapter(java.lang.Class)
193 */
194
195 public <T> ComponentAdapter<T> getComponentAdapter(final Class<T> componentType, final NameBinding componentNameBinding) {
196 if (logger.isDebugEnabled()) {
197 logger.debug("Locating component adapter with type " + componentType);
198 }
199
200 ComponentAdapter<T> ca = delegate.getComponentAdapter(componentType, componentNameBinding);
201
202 if (ca == null) {
203 onKeyOrTypeDoesNotExistInContainer(ca, logger);
204 }
205 return ca;
206 }
207
208 /**
209 * {@inheritDoc}
210 *
211 * @return Collection or null.
212 *
213 * @see org.picocontainer.PicoContainer#getComponentAdapters()
214 */
215 public Collection<ComponentAdapter<?>> getComponentAdapters() {
216 if (logger.isDebugEnabled()) {
217 logger.debug("Grabbing all component adapters for container: " + delegate);
218 }
219 return delegate.getComponentAdapters();
220 }
221
222 /**
223 * {@inheritDoc}
224 *
225 * @param componentType
226 *
227 * @return List of ComponentAdapters
228 *
229 * @see org.picocontainer.PicoContainer#getComponentAdapters(java.lang.Class)
230 */
231 public <T> List<ComponentAdapter<T>> getComponentAdapters(final Class<T> componentType) {
232 if (logger.isDebugEnabled()) {
233 logger.debug("Grabbing all component adapters for container: " + delegate + " of type: "
234 + componentType.getName());
235 }
236 return delegate.getComponentAdapters(componentType);
237 }
238
239 public <T> List<ComponentAdapter<T>> getComponentAdapters(final Class<T> componentType, final Class<? extends Annotation> binding) {
240 if (logger.isDebugEnabled()) {
241 logger.debug("Grabbing all component adapters for container: " + delegate + " of type: "
242 + componentType.getName() + ", binding:" + binding.getName());
243 }
244 return delegate.getComponentAdapters(componentType, binding);
245 }
246
247 public <T> ComponentAdapter<T> getComponentAdapter(final Class<T> componentType, final Class<? extends Annotation> binding) {
248 if (logger.isDebugEnabled()) {
249 logger.debug("Grabbing component adapter for container: " + delegate + " of type: "
250 + componentType.getName() + ", binding:" + binding.getName());
251 }
252 return delegate.getComponentAdapter(componentType, binding);
253 }
254
255 /**
256 * {@inheritDoc}
257 *
258 * @param componentKeyOrType
259 *
260 * @return
261 *
262 * @see org.picocontainer.PicoContainer#getComponent(java.lang.Object)
263 */
264 public Object getComponent(final Object componentKeyOrType) {
265
266 if (logger.isDebugEnabled()) {
267 logger.debug("Attempting to load component instance with "
268 + (componentKeyOrType instanceof Class ? "type" : "key")
269 + ": "
270 + (componentKeyOrType instanceof Class
271 ? ((Class)componentKeyOrType).getName()
272 : componentKeyOrType)
273 + " for container "
274 + delegate);
275
276 }
277
278 Object result = delegate.getComponent(componentKeyOrType);
279 if (result == null) {
280 onKeyOrTypeDoesNotExistInContainer(componentKeyOrType, logger);
281 }
282
283 return result;
284 }
285
286 public Object getComponent(final Object componentKeyOrType, final Type into) {
287 if (logger.isDebugEnabled()) {
288 logger.debug("Attempting to load component instance with "
289 + (componentKeyOrType instanceof Class ? "type" : "key")
290 + ": "
291 + (componentKeyOrType instanceof Class
292 ? ((Class)componentKeyOrType).getName()
293 : componentKeyOrType)
294 + " for container "
295 + delegate);
296
297 }
298 Object result = delegate.getComponent(componentKeyOrType, into);
299 if (result == null) {
300 onKeyOrTypeDoesNotExistInContainer(componentKeyOrType, logger);
301 }
302
303 return result;
304 }
305
306 public <T> T getComponent(final Class<T> componentType) {
307 return componentType.cast(getComponent((Object)componentType));
308 }
309
310 public <T> T getComponent(final Class<T> componentType, final Class<? extends Annotation> binding) {
311 if (logger.isDebugEnabled()) {
312 logger.debug("Attempting to load component instance with "
313 + "type"
314 + ": "
315 + componentType.getName()
316 + " for container "
317 + delegate);
318
319 }
320 return delegate.getComponent(componentType, binding);
321 }
322
323 /**
324 * {@inheritDoc}
325 *
326 * @param componentType
327 * @return
328 * @see org.picocontainer.PicoContainer#getComponent(java.lang.Class)
329 */
330 // public Object getComponent(final Class componentType) {
331 // if (logger.isDebugEnabled()) {
332 // logger.debug("Attempting to load component instance with type: " + componentType + " for container "
333 // + delegate);
334 //
335 // }
336 //
337 // Object result = delegate.getComponent(componentType);
338 // if (result == null) {
339 // if (logger.isInfoEnabled()) {
340 // logger.info("No component of type " + componentType.getName() + " was found in container: " + delegate);
341 // }
342 // }
343 //
344 // return result;
345 // }
346
347 /**
348 * {@inheritDoc}
349 *
350 * @return
351 *
352 * @see org.picocontainer.PicoContainer#getComponents()
353 */
354 public List getComponents() {
355 if (logger.isDebugEnabled()) {
356 logger.debug("Retrieving all component instances for container " + delegate);
357 }
358 return delegate.getComponents();
359 }
360
361 /**
362 * {@inheritDoc}
363 *
364 * @param componentType
365 *
366 * @return
367 *
368 * @see org.picocontainer.PicoContainer#getComponents(java.lang.Class)
369 */
370 public <T> List<T> getComponents(final Class<T> componentType) {
371 if (logger.isDebugEnabled()) {
372 logger.debug("Loading all component instances of type " + componentType + " for container " + delegate);
373 }
374 List<T> result = delegate.getComponents(componentType);
375 if (result == null || result.isEmpty()) {
376 if (logger.isInfoEnabled()) {
377 logger.info("Could not find any components " + " in container or parent container.");
378 }
379 }
380
381 return result;
382 }
383
384 /**
385 * {@inheritDoc}
386 *
387 * @return
388 *
389 * @see org.picocontainer.PicoContainer#getParent()
390 */
391 public PicoContainer getParent() {
392 if (logger.isDebugEnabled()) {
393 logger.debug("Retrieving the parent for container " + delegate);
394 }
395
396 return delegate.getParent();
397 }
398
399 /**
400 * {@inheritDoc}
401 *
402 * @return
403 *
404 * @see org.picocontainer.MutablePicoContainer#makeChildContainer()
405 */
406 public MutablePicoContainer makeChildContainer() {
407 if (logger.isDebugEnabled()) {
408 logger.debug("Making child container for container " + delegate);
409 }
410
411 // Wrap the new delegate
412 return new Log4jTracingContainerDecorator(delegate.makeChildContainer());
413 }
414
415 /**
416 * {@inheritDoc}
417 *
418 * @param componentAdapter
419 *
420 * @return
421 *
422 * @see org.picocontainer.MutablePicoContainer#addAdapter(org.picocontainer.ComponentAdapter)
423 */
424 public MutablePicoContainer addAdapter(final ComponentAdapter componentAdapter) {
425 if (logger.isDebugEnabled()) {
426 logger.debug("Registering component adapter " + componentAdapter);
427 }
428
429 return delegate.addAdapter(componentAdapter);
430 }
431
432 /**
433 * {@inheritDoc}
434 *
435 * @param componentKey
436 * @param componentImplementationOrInstance
437 *
438 * @param parameters
439 *
440 * @return
441 */
442 public MutablePicoContainer addComponent(final Object componentKey,
443 final Object componentImplementationOrInstance,
444 final Parameter... parameters)
445 {
446
447 if (logger.isDebugEnabled()) {
448 logger.debug("Registering component "
449 + (componentImplementationOrInstance instanceof Class ? "implementation" : "instance")
450 + " with key " + componentKey + " and implementation "
451 + (componentImplementationOrInstance instanceof Class
452 ? ((Class)componentImplementationOrInstance).getCanonicalName()
453 : componentKey.getClass()) + " using parameters " + parameters);
454 }
455
456 return delegate.addComponent(componentKey, componentImplementationOrInstance, parameters);
457 }
458
459 /**
460 * {@inheritDoc}
461 *
462 * @param implOrInstance
463 *
464 * @return
465 *
466 * @see org.picocontainer.MutablePicoContainer#addComponent(java.lang.Object)
467 */
468 public MutablePicoContainer addComponent(final Object implOrInstance) {
469 if (logger.isDebugEnabled()) {
470 logger.debug("Registering component impl or instance " + implOrInstance + "(class: "
471 + ((implOrInstance != null) ? implOrInstance.getClass().getName() : " null "));
472 }
473
474 return delegate.addComponent(implOrInstance);
475 }
476
477 public MutablePicoContainer addConfig(final String name, final Object val) {
478 if (logger.isDebugEnabled()) {
479 logger.debug("Registering config: " + name);
480 }
481
482 return delegate.addConfig(name, val);
483
484 }
485
486 /**
487 * {@inheritDoc}
488 *
489 * @param child
490 *
491 * @return
492 *
493 * @see org.picocontainer.MutablePicoContainer#removeChildContainer(org.picocontainer.PicoContainer)
494 */
495 public boolean removeChildContainer(final PicoContainer child) {
496 if (logger.isDebugEnabled()) {
497 logger.debug("Removing child container: " + child + " from parent: " + delegate);
498 }
499 return delegate.removeChildContainer(child);
500 }
501
502 /**
503 * {@inheritDoc}
504 *
505 * @see org.picocontainer.Startable#start()
506 */
507 public void start() {
508 if (logger.isInfoEnabled()) {
509 logger.info("Starting Container " + delegate);
510 }
511
512 delegate.start();
513 }
514
515 /**
516 * {@inheritDoc}
517 *
518 * @see org.picocontainer.Startable#stop()
519 */
520 public void stop() {
521 if (logger.isInfoEnabled()) {
522 logger.info("Stopping Container " + delegate);
523 }
524 delegate.stop();
525 }
526
527 /**
528 * {@inheritDoc}
529 *
530 * @param componentKey
531 *
532 * @return
533 *
534 * @see org.picocontainer.MutablePicoContainer#removeComponent(java.lang.Object)
535 */
536 public ComponentAdapter removeComponent(final Object componentKey) {
537 if (logger.isDebugEnabled()) {
538 logger.debug("Unregistering component " + componentKey + " from container " + delegate);
539 }
540
541 return delegate.removeComponent(componentKey);
542 }
543
544 /**
545 * {@inheritDoc}
546 *
547 * @param componentInstance
548 *
549 * @return
550 *
551 * @see org.picocontainer.MutablePicoContainer#removeComponentByInstance(java.lang.Object)
552 */
553 public ComponentAdapter removeComponentByInstance(final Object componentInstance) {
554 if (logger.isDebugEnabled()) {
555 logger.debug("Unregistering component by instance (" + componentInstance + ") from container " + delegate);
556 }
557
558 return delegate.removeComponentByInstance(componentInstance);
559 }
560
561 /**
562 * Retrieves the logger instance used by this decorator.
563 *
564 * @return Logger instance.
565 */
566 public Logger getLoggerUsed() {
567 return this.logger;
568 }
569
570 private void readObject(final ObjectInputStream s) throws java.io.IOException, java.lang.ClassNotFoundException {
571
572 s.defaultReadObject();
573 String loggerName = s.readUTF();
574 logger = Logger.getLogger(loggerName);
575 }
576
577 private void writeObject(final ObjectOutputStream s) throws java.io.IOException {
578 s.defaultWriteObject();
579 s.writeUTF(logger.getName());
580 }
581
582 public MutablePicoContainer change(final Properties... properties) {
583 return delegate.change(properties);
584 }
585
586 public MutablePicoContainer as(final Properties... properties) {
587 return delegate.as(properties);
588 }
589
590 public void setName(String name) {
591 delegate.setName(name);
592 }
593
594 public void setLifecycleState(LifecycleState lifecycleState) {
595 delegate.setLifecycleState(lifecycleState);
596 }
597 }