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