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 }