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 * 009 *****************************************************************************/ 010 package org.picocontainer.monitors; 011 012 import java.lang.reflect.Constructor; 013 import java.lang.reflect.Member; 014 import java.lang.reflect.Method; 015 import java.util.ArrayList; 016 import java.util.Collection; 017 import java.util.List; 018 019 import org.picocontainer.ComponentAdapter; 020 import org.picocontainer.ComponentMonitor; 021 import org.picocontainer.MutablePicoContainer; 022 import org.picocontainer.PicoContainer; 023 import org.picocontainer.PicoException; 024 import org.picocontainer.PicoLifecycleException; 025 import org.picocontainer.injectors.AbstractInjector; 026 027 /** 028 * A {@link ComponentMonitor} which collects lifecycle failures 029 * and rethrows them on demand after the failures. 030 * 031 * @author Paul Hammant 032 * @author Mauro Talevi 033 */ 034 @SuppressWarnings("serial") 035 public final class LifecycleComponentMonitor implements ComponentMonitor { 036 037 /** 038 * Delegate for chained component monitors. 039 */ 040 private final ComponentMonitor delegate; 041 042 private final List<RuntimeException> lifecycleFailures = new ArrayList<RuntimeException>(); 043 044 public LifecycleComponentMonitor(ComponentMonitor delegate) { 045 this.delegate = delegate; 046 } 047 048 public LifecycleComponentMonitor() { 049 this(new NullComponentMonitor()); 050 } 051 052 public <T> Constructor<T> instantiating(PicoContainer container, ComponentAdapter<T> componentAdapter, 053 Constructor<T> constructor) { 054 return delegate.instantiating(container, componentAdapter, constructor); 055 } 056 057 public <T> void instantiated(PicoContainer container, ComponentAdapter<T> componentAdapter, 058 Constructor<T> constructor, 059 Object instantiated, 060 Object[] parameters, 061 long duration) { 062 delegate.instantiated(container, componentAdapter, constructor, instantiated, parameters, duration); 063 } 064 065 public <T> void instantiationFailed(PicoContainer container, 066 ComponentAdapter<T> componentAdapter, 067 Constructor<T> constructor, 068 Exception cause) { 069 delegate.instantiationFailed(container, componentAdapter, constructor, cause); 070 } 071 072 public void invoking(PicoContainer container, 073 ComponentAdapter<?> componentAdapter, 074 Member member, 075 Object instance) { 076 delegate.invoking(container, componentAdapter, member, instance); 077 } 078 079 public void invoked(PicoContainer container, 080 ComponentAdapter<?> componentAdapter, 081 Method method, 082 Object instance, 083 long duration) { 084 delegate.invoked(container, componentAdapter, method, instance, duration); 085 } 086 087 public void invocationFailed(Member member, Object instance, Exception cause) { 088 delegate.invocationFailed(member, instance, cause); 089 } 090 091 public void lifecycleInvocationFailed(MutablePicoContainer container, 092 ComponentAdapter<?> componentAdapter, Method method, 093 Object instance, 094 RuntimeException cause) { 095 lifecycleFailures.add(cause); 096 try { 097 delegate.lifecycleInvocationFailed(container, componentAdapter, method, instance, cause); 098 } catch (PicoLifecycleException e) { 099 // do nothing, exception already logged for later rethrow. 100 } 101 } 102 103 public Object noComponentFound(MutablePicoContainer container, Object componentKey) { 104 return delegate.noComponentFound(container, componentKey); 105 } 106 107 public AbstractInjector newInjectionFactory(AbstractInjector abstractInjector) { 108 return delegate.newInjectionFactory(abstractInjector); 109 } 110 111 112 public void rethrowLifecycleFailuresException() { 113 throw new LifecycleFailuresException(lifecycleFailures); 114 } 115 116 /** 117 * Subclass of {@link PicoException} that is thrown when the collected 118 * lifecycle failures need to be be collectively rethrown. 119 * 120 * @author Paul Hammant 121 * @author Mauro Talevi 122 */ 123 public final class LifecycleFailuresException extends PicoException { 124 125 126 private final List<RuntimeException> lifecycleFailures; 127 128 public LifecycleFailuresException(List<RuntimeException> lifecycleFailures) { 129 this.lifecycleFailures = lifecycleFailures; 130 } 131 132 public String getMessage() { 133 StringBuffer message = new StringBuffer(); 134 for (Object lifecycleFailure : lifecycleFailures) { 135 Exception failure = (Exception)lifecycleFailure; 136 message.append(failure.getMessage()).append("; "); 137 } 138 return message.toString(); 139 } 140 141 public Collection<RuntimeException> getFailures() { 142 return lifecycleFailures; 143 } 144 } 145 }