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