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