diff --git a/src/main/java/teetime/framework/A4StageAttributeSetter.java b/src/main/java/teetime/framework/A4StageAttributeSetter.java index 3b57d5eb50abbdf6aeb7225b0759698383755485..98373e41c8f687a6644a7fdff87a77377a498240 100644 --- a/src/main/java/teetime/framework/A4StageAttributeSetter.java +++ b/src/main/java/teetime/framework/A4StageAttributeSetter.java @@ -46,7 +46,7 @@ class A4StageAttributeSetter { } private void setAttributes(final Stage threadableStage, final Set<Stage> intraStages) { - threadableStage.setExceptionHandler(configuration.getFactory().createInstance()); + threadableStage.setExceptionHandler(configuration.getFactory().createInstance(threadableStage.getOwningThread())); // threadableStage.setOwningThread(owningThread); threadableStage.setOwningContext(configuration.getContext()); diff --git a/src/main/java/teetime/framework/Configuration.java b/src/main/java/teetime/framework/Configuration.java index 2ffa6376a0768cd579f29f3a30af8d6e85531124..de6ba150e10440c8800b09b368b0e3ce3f138da0 100644 --- a/src/main/java/teetime/framework/Configuration.java +++ b/src/main/java/teetime/framework/Configuration.java @@ -15,7 +15,7 @@ */ package teetime.framework; -import teetime.framework.exceptionHandling.IExceptionListenerFactory; +import teetime.framework.exceptionHandling.AbstractExceptionListenerFactory; import teetime.framework.exceptionHandling.TerminatingExceptionListenerFactory; /** @@ -28,7 +28,7 @@ import teetime.framework.exceptionHandling.TerminatingExceptionListenerFactory; */ public abstract class Configuration extends AbstractCompositeStage { - private final IExceptionListenerFactory<?> factory; + private final AbstractExceptionListenerFactory<?> factory; private final ConfigurationContext context; private boolean initialized; @@ -39,7 +39,7 @@ public abstract class Configuration extends AbstractCompositeStage { this(new TerminatingExceptionListenerFactory()); } - protected Configuration(final IExceptionListenerFactory<?> factory) { + protected Configuration(final AbstractExceptionListenerFactory<?> factory) { this.factory = factory; this.context = new ConfigurationContext(this); } @@ -60,7 +60,7 @@ public abstract class Configuration extends AbstractCompositeStage { this.executed = executed; } - public IExceptionListenerFactory<?> getFactory() { + public AbstractExceptionListenerFactory<?> getFactory() { return factory; } diff --git a/src/main/java/teetime/framework/Execution.java b/src/main/java/teetime/framework/Execution.java index 782f0ea2a189d2b167d7108e1d7616f99cb75017..a8c98167c67bbf475a3957a15147aecd55b678b3 100644 --- a/src/main/java/teetime/framework/Execution.java +++ b/src/main/java/teetime/framework/Execution.java @@ -15,6 +15,8 @@ */ package teetime.framework; +import java.util.List; +import java.util.Map.Entry; import java.util.Set; import teetime.framework.signal.ValidatingSignal; @@ -104,7 +106,14 @@ public final class Execution<T extends Configuration> { * @since 2.0 */ public void waitForTermination() { + int numExceptions = 0; configurationContext.waitForConfigurationToTerminate(); + for (Entry<Thread, List<Exception>> entry : configuration.getFactory().getThreadExceptionsMap().entrySet()) { + numExceptions += entry.getValue().size(); + } + if (numExceptions != 0) { + throw new ExecutionException(configuration.getFactory().getThreadExceptionsMap()); + } } // TODO: implement diff --git a/src/main/java/teetime/framework/ExecutionException.java b/src/main/java/teetime/framework/ExecutionException.java index f33901b38239210b2aa5cf3df5563cd0cba1cc5c..bc6945bca79997767d294f70f7975bbd59b035ce 100644 --- a/src/main/java/teetime/framework/ExecutionException.java +++ b/src/main/java/teetime/framework/ExecutionException.java @@ -15,24 +15,23 @@ */ package teetime.framework; -import java.util.Collection; - -import teetime.util.ThreadThrowableContainer; +import java.util.List; +import java.util.Map; /** * Represents a exception, which is thrown by an analysis, if any problems occured within its execution. * A collection of thrown exceptions within the analysis can be retrieved with {@link #getThrownExceptions()}. * - * @since 1.1 + * @since 2.0 */ public class ExecutionException extends RuntimeException { private static final long serialVersionUID = 7486086437171884298L; - private final Collection<ThreadThrowableContainer> exceptions; + private final Map<Thread, List<Exception>> exceptions; - public ExecutionException(final Collection<ThreadThrowableContainer> exceptions) { - super((exceptions.size() == 1) ? exceptions.toString() : "Error(s) while execution. Check thrown exception(s)."); + public ExecutionException(final Map<Thread, List<Exception>> exceptions) { + super((exceptions.size() == 1) ? exceptions.toString() : exceptions.size() + " error(s) while execution. Check thrown exception(s)."); this.exceptions = exceptions; } @@ -40,9 +39,9 @@ public class ExecutionException extends RuntimeException { * Returns all exceptions thrown within the execution. * These are passed on as pairs of threads and throwables, to indicate a exception's context. * - * @return a collection of pairs + * @return a thread-exceptionlist-map */ - public Collection<ThreadThrowableContainer> getThrownExceptions() { + public Map<Thread, List<Exception>> getThrownExceptions() { return exceptions; } diff --git a/src/main/java/teetime/framework/Stage.java b/src/main/java/teetime/framework/Stage.java index dcc6b97f8cd2f47377410ac6e5f16f02dd642c94..4851210d210ef264edcdce57a111ce091377db97 100644 --- a/src/main/java/teetime/framework/Stage.java +++ b/src/main/java/teetime/framework/Stage.java @@ -121,7 +121,7 @@ public abstract class Stage { } catch (TerminateException e) { throw e; } catch (Exception e) { - final FurtherExecution furtherExecution = this.exceptionListener.onStageException(e, this); + final FurtherExecution furtherExecution = this.exceptionListener.reportException(e, this); if (furtherExecution == FurtherExecution.TERMINATE) { throw TerminateException.INSTANCE; } diff --git a/src/main/java/teetime/framework/exceptionHandling/AbstractExceptionListener.java b/src/main/java/teetime/framework/exceptionHandling/AbstractExceptionListener.java index c34480fa78fa3f8643af4d52e01804a825272683..81cc2f0297258ddb89dadd5c094f9b28bc41ba71 100644 --- a/src/main/java/teetime/framework/exceptionHandling/AbstractExceptionListener.java +++ b/src/main/java/teetime/framework/exceptionHandling/AbstractExceptionListener.java @@ -15,6 +15,9 @@ */ package teetime.framework.exceptionHandling; +import java.util.ArrayList; +import java.util.List; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,6 +30,9 @@ import teetime.framework.Stage; */ public abstract class AbstractExceptionListener { + private final List<Exception> exceptionsList = new ArrayList<Exception>(); + private final boolean logExceptions; + public enum FurtherExecution { CONTINUE, TERMINATE } @@ -36,8 +42,9 @@ public abstract class AbstractExceptionListener { */ protected final Logger logger; - public AbstractExceptionListener() { + protected AbstractExceptionListener(final boolean shouldLogExceptions) { this.logger = LoggerFactory.getLogger(this.getClass().getCanonicalName()); + this.logExceptions = shouldLogExceptions; } /** @@ -52,4 +59,15 @@ public abstract class AbstractExceptionListener { */ public abstract FurtherExecution onStageException(Exception e, Stage throwingStage); + public List<Exception> getLoggedExceptions() { + return exceptionsList; + } + + public FurtherExecution reportException(final Exception e, final Stage stage) { + if (logExceptions) { + exceptionsList.add(e); + } + return onStageException(e, stage); + } + } diff --git a/src/main/java/teetime/framework/exceptionHandling/IExceptionListenerFactory.java b/src/main/java/teetime/framework/exceptionHandling/AbstractExceptionListenerFactory.java similarity index 55% rename from src/main/java/teetime/framework/exceptionHandling/IExceptionListenerFactory.java rename to src/main/java/teetime/framework/exceptionHandling/AbstractExceptionListenerFactory.java index cc0f1463883c089c8149a155f104c07204e1e091..a61f8d9fbc72005d4d3d3b5b097fbdf9a5b8f4a2 100644 --- a/src/main/java/teetime/framework/exceptionHandling/IExceptionListenerFactory.java +++ b/src/main/java/teetime/framework/exceptionHandling/AbstractExceptionListenerFactory.java @@ -15,8 +15,24 @@ */ package teetime.framework.exceptionHandling; -public interface IExceptionListenerFactory<T extends AbstractExceptionListener> { +import java.util.HashMap; +import java.util.List; +import java.util.Map; - public T createInstance(); +public abstract class AbstractExceptionListenerFactory<T extends AbstractExceptionListener> { + + private final Map<Thread, List<Exception>> threadExceptionsMap = new HashMap<Thread, List<Exception>>(); + + protected abstract T createInstance(); + + public T createInstance(final Thread thread) { + T instance = createInstance(); + threadExceptionsMap.put(thread, instance.getLoggedExceptions()); + return instance; + } + + public Map<Thread, List<Exception>> getThreadExceptionsMap() { + return threadExceptionsMap; + } } diff --git a/src/main/java/teetime/framework/exceptionHandling/IgnoringExceptionListener.java b/src/main/java/teetime/framework/exceptionHandling/IgnoringExceptionListener.java index c46c70a2a585341536612753eaae83cfa3bec38d..3eb5445131482966918d4137e0faee2dc31ec070 100644 --- a/src/main/java/teetime/framework/exceptionHandling/IgnoringExceptionListener.java +++ b/src/main/java/teetime/framework/exceptionHandling/IgnoringExceptionListener.java @@ -19,6 +19,10 @@ import teetime.framework.Stage; class IgnoringExceptionListener extends AbstractExceptionListener { + IgnoringExceptionListener() { + super(false); + } + @Override public FurtherExecution onStageException(final Exception e, final Stage throwingStage) { return FurtherExecution.CONTINUE; diff --git a/src/main/java/teetime/framework/exceptionHandling/IgnoringExceptionListenerFactory.java b/src/main/java/teetime/framework/exceptionHandling/IgnoringExceptionListenerFactory.java index 200e5eb2c2e840f8aa9c52187861f74de72ac52a..ff3d76467af26f690e963426b18a8b27195f07bc 100644 --- a/src/main/java/teetime/framework/exceptionHandling/IgnoringExceptionListenerFactory.java +++ b/src/main/java/teetime/framework/exceptionHandling/IgnoringExceptionListenerFactory.java @@ -15,10 +15,10 @@ */ package teetime.framework.exceptionHandling; -public class IgnoringExceptionListenerFactory implements IExceptionListenerFactory { +public class IgnoringExceptionListenerFactory extends AbstractExceptionListenerFactory<IgnoringExceptionListener> { @Override - public AbstractExceptionListener createInstance() { + protected final IgnoringExceptionListener createInstance() { return new IgnoringExceptionListener(); } diff --git a/src/main/java/teetime/framework/exceptionHandling/LoggingExceptionListener.java b/src/main/java/teetime/framework/exceptionHandling/LoggingExceptionListener.java index ab7f91768616042130b8430835f6498f5b9a0ef1..8fee623cb29f4068f6d98cedcf68e1dab33cb1ba 100644 --- a/src/main/java/teetime/framework/exceptionHandling/LoggingExceptionListener.java +++ b/src/main/java/teetime/framework/exceptionHandling/LoggingExceptionListener.java @@ -19,6 +19,10 @@ import teetime.framework.Stage; class LoggingExceptionListener extends AbstractExceptionListener { + LoggingExceptionListener() { + super(true); + } + @Override public FurtherExecution onStageException(final Exception e, final Stage throwingStage) { logger.warn("Exception occurred in " + throwingStage.getId(), e); diff --git a/src/main/java/teetime/framework/exceptionHandling/LoggingExceptionListenerFactory.java b/src/main/java/teetime/framework/exceptionHandling/LoggingExceptionListenerFactory.java index 3eb9130fd221208f455b9fcd619726ad98185e41..fb5895e026af801eeff5f28656a73376d26c05f8 100644 --- a/src/main/java/teetime/framework/exceptionHandling/LoggingExceptionListenerFactory.java +++ b/src/main/java/teetime/framework/exceptionHandling/LoggingExceptionListenerFactory.java @@ -15,10 +15,10 @@ */ package teetime.framework.exceptionHandling; -public class LoggingExceptionListenerFactory implements IExceptionListenerFactory { +public class LoggingExceptionListenerFactory extends AbstractExceptionListenerFactory<LoggingExceptionListener> { @Override - public AbstractExceptionListener createInstance() { + protected final LoggingExceptionListener createInstance() { return new LoggingExceptionListener(); } diff --git a/src/main/java/teetime/framework/exceptionHandling/TerminatingExceptionListener.java b/src/main/java/teetime/framework/exceptionHandling/TerminatingExceptionListener.java index b8bcf36df06c6f44d91270df3fa428c0d66e9f69..2490c0e43ad4a15b4ffd47baf86521a642cd1c07 100644 --- a/src/main/java/teetime/framework/exceptionHandling/TerminatingExceptionListener.java +++ b/src/main/java/teetime/framework/exceptionHandling/TerminatingExceptionListener.java @@ -25,7 +25,7 @@ class TerminatingExceptionListener extends AbstractExceptionListener { private final List<Exception> exceptions = new ArrayList<Exception>(); TerminatingExceptionListener() { - // should only be instantiated by its factory + super(true); } @Override diff --git a/src/main/java/teetime/framework/exceptionHandling/TerminatingExceptionListenerFactory.java b/src/main/java/teetime/framework/exceptionHandling/TerminatingExceptionListenerFactory.java index 354a04cb0889c2fc1229c4e4ca1cb888e2d7b47a..7ad763e6a1f1418e257799b91fa0ebf9ffce2fd4 100644 --- a/src/main/java/teetime/framework/exceptionHandling/TerminatingExceptionListenerFactory.java +++ b/src/main/java/teetime/framework/exceptionHandling/TerminatingExceptionListenerFactory.java @@ -15,7 +15,7 @@ */ package teetime.framework.exceptionHandling; -public class TerminatingExceptionListenerFactory implements IExceptionListenerFactory<TerminatingExceptionListener> { +public class TerminatingExceptionListenerFactory extends AbstractExceptionListenerFactory<TerminatingExceptionListener> { @Override public TerminatingExceptionListener createInstance() { diff --git a/src/site/markdown/wiki b/src/site/markdown/wiki index 2c3239a10d4bac6e0b97ecbf114cc67a1d04b2be..709c839c447a50c93b37fcc633a01297115d4823 160000 --- a/src/site/markdown/wiki +++ b/src/site/markdown/wiki @@ -1 +1 @@ -Subproject commit 2c3239a10d4bac6e0b97ecbf114cc67a1d04b2be +Subproject commit 709c839c447a50c93b37fcc633a01297115d4823 diff --git a/src/test/java/teetime/framework/RunnableConsumerStageTest.java b/src/test/java/teetime/framework/RunnableConsumerStageTest.java index 251a49610d2833610eded1320455997fb60842be..3984a2fe707b09b76d72a995fe0dd6cb406df161 100644 --- a/src/test/java/teetime/framework/RunnableConsumerStageTest.java +++ b/src/test/java/teetime/framework/RunnableConsumerStageTest.java @@ -18,16 +18,13 @@ package teetime.framework; import static org.junit.Assert.assertEquals; import java.lang.Thread.State; -import java.util.ArrayList; -import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.junit.Ignore; import org.junit.Test; -import teetime.util.ThreadThrowableContainer; - -import com.google.common.base.Joiner; - public class RunnableConsumerStageTest { @Test @@ -118,17 +115,17 @@ public class RunnableConsumerStageTest { } private void start(final Execution<?> execution) { - Collection<ThreadThrowableContainer> exceptions = new ArrayList<ThreadThrowableContainer>(); + Map<Thread, List<Exception>> exceptions = new HashMap<Thread, List<Exception>>(); try { execution.executeBlocking(); } catch (ExecutionException e) { exceptions = e.getThrownExceptions(); } - for (ThreadThrowableContainer pair : exceptions) { - System.err.println(pair.getThrowable()); - System.err.println(Joiner.on("\n").join(pair.getThrowable().getStackTrace())); - throw new AssertionError(pair.getThrowable()); - } + // for (ThreadThrowableContainer pair : exceptions) { + // System.err.println(pair.getThrowable()); + // System.err.println(Joiner.on("\n").join(pair.getThrowable().getStackTrace())); + // throw new AssertionError(pair.getThrowable()); + // } assertEquals(0, exceptions.size()); } } diff --git a/src/test/java/teetime/framework/exceptionHandling/TestListener.java b/src/test/java/teetime/framework/exceptionHandling/TestListener.java index 7a8826a9fff58f8d7a84225fa485e3c1e1420e1e..06b32bcd2c3971fe9838776229c0b651ba68fc7e 100644 --- a/src/test/java/teetime/framework/exceptionHandling/TestListener.java +++ b/src/test/java/teetime/framework/exceptionHandling/TestListener.java @@ -19,6 +19,10 @@ import teetime.framework.Stage; public class TestListener extends AbstractExceptionListener { + protected TestListener() { + super(false); + } + private int numExceptionsInvoked; @Override diff --git a/src/test/java/teetime/framework/exceptionHandling/TestListenerFactory.java b/src/test/java/teetime/framework/exceptionHandling/TestListenerFactory.java index 270f4f0bd5c5501ffe9b4dac5cc46292af24fd69..b4ebf7141b8967ad608b6ba6c7097b3a50a3a135 100644 --- a/src/test/java/teetime/framework/exceptionHandling/TestListenerFactory.java +++ b/src/test/java/teetime/framework/exceptionHandling/TestListenerFactory.java @@ -18,12 +18,12 @@ package teetime.framework.exceptionHandling; import java.util.ArrayList; import java.util.List; -public class TestListenerFactory implements IExceptionListenerFactory { +public class TestListenerFactory extends AbstractExceptionListenerFactory<TestListener> { private final List<TestListener> instances = new ArrayList<TestListener>(); @Override - public AbstractExceptionListener createInstance() { + public TestListener createInstance() { TestListener listener = new TestListener(); instances.add(listener); return listener;