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