diff options
author | bvosburgh | 2009-10-08 13:55:41 +0000 |
---|---|---|
committer | bvosburgh | 2009-10-08 13:55:41 +0000 |
commit | d2aa7cb47ed229aa124ace66add8a91e67804978 (patch) | |
tree | 2a558515085d5c492d4eb1c02ca58af1be25080a /jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal | |
parent | d3c4d9da79b36435a3e856fae1be29f1f293e8fe (diff) | |
download | webtools.dali-d2aa7cb47ed229aa124ace66add8a91e67804978.tar.gz webtools.dali-d2aa7cb47ed229aa124ace66add8a91e67804978.tar.xz webtools.dali-d2aa7cb47ed229aa124ace66add8a91e67804978.zip |
handle synchronization exceptions
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal')
6 files changed, 118 insertions, 18 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/CompositeException.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/CompositeException.java new file mode 100644 index 0000000000..69d5f89166 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/CompositeException.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.utility.internal; + +public class CompositeException + extends RuntimeException +{ + private final Throwable[] exceptions; + private static final long serialVersionUID = 1L; + + public CompositeException(Throwable[] exceptions) { + super(); + this.exceptions = exceptions; + } + + public Throwable[] getExceptions() { + return this.exceptions; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/AsynchronousSynchronizer.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/AsynchronousSynchronizer.java index 300bee3a66..75d6fea7fa 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/AsynchronousSynchronizer.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/AsynchronousSynchronizer.java @@ -9,7 +9,10 @@ ******************************************************************************/ package org.eclipse.jpt.utility.internal.synchronizers; +import java.util.Vector; + import org.eclipse.jpt.utility.Command; +import org.eclipse.jpt.utility.internal.CompositeException; import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.SynchronizedBoolean; @@ -50,6 +53,11 @@ public class AsynchronousSynchronizer */ private Thread thread; + /** + * A list of the uncaught exceptions thrown by the command. + */ + final Vector<Throwable> exceptions = new Vector<Throwable>(); + // ********** construction ********** @@ -82,7 +90,21 @@ public class AsynchronousSynchronizer /** * Build and start the synchronization thread, but postpone the first - * synchronization until requested, via {@link #synchronize()}. + * synchronization until requested, i.e. via a call to + * {@link #synchronize()}. + * <p> + * Note: We don't clear the "synchronize" flag here; so if the flag has + * been set <em>before</em> getting here, the first synchronization will + * start promptly (albeit, asynchronously). + * The "synchronize" flag will be set if:<ul> + * <li>{@link #synchronize()} was called after the synchronizer was + * constructed but before {@link #start()} was called; or + * <li>{@link #synchronize()} was called after {@link #stop()} was called + * but before {@link #start()} was called (to restart the synchronizer); or + * <li>{@link #stop()} was called when there was an outstanding request + * for a synchronization (i.e. the "synchronization" flag was set at + * the time {@link #stop()} was called) + * </ul> */ public synchronized void start() { if (this.thread != null) { @@ -101,18 +123,27 @@ public class AsynchronousSynchronizer } /** - * Set the "synchronize" flag so the synchronization thread will execute - * a synchronization. + * Set the "synchronize" flag so the synchronization thread will either<ul> + * <li>if the thread is quiesced, start a synchronization immediately, or + * <li>if the thread is currently executing a synchronization, execute another + * synchronization once the current synchronization is complete + * </ul> */ public void synchronize() { this.synchronizeFlag.setTrue(); } + /** + * Interrupt the synchronization thread so that it stops executing at the + * end of the current synchronization. Suspend the current thread until + * the synchronization thread is finished executing. If any uncaught + * exceptions were thrown while the synchronization thread was executing, + * wrap them in a composite exception and throw the composite exception. + */ public synchronized void stop() { if (this.thread == null) { throw new IllegalStateException("The Synchronizer was not started."); //$NON-NLS-1$ } - this.synchronizeFlag.setFalse(); this.thread.interrupt(); try { this.thread.join(); @@ -123,6 +154,12 @@ public class AsynchronousSynchronizer // after its current execution - we just won't wait around for it... } this.thread = null; + + if (this.exceptions.size() > 0) { + Throwable[] temp = this.exceptions.toArray(new Throwable[this.exceptions.size()]); + this.exceptions.clear(); + throw new CompositeException(temp); + } } @Override @@ -142,7 +179,9 @@ public class AsynchronousSynchronizer * the command will be re-executed immediately. Stop the thread by calling * {@link Thread#interrupt()}. */ - class RunnableSynchronization implements Runnable { + class RunnableSynchronization + implements Runnable + { /** The client-supplied command that executes on this thread. */ private final Command command; @@ -181,9 +220,21 @@ public class AsynchronousSynchronizer } /** + * Execute the client-supplied command. Do not allow any unhandled + * exceptions to kill the thread. Store them up for later pain. + */ + private void execute() { + try { + this.execute_(); + } catch (Throwable ex) { + AsynchronousSynchronizer.this.exceptions.add(ex); + } + } + + /** * Execute the client-supplied command. */ - void execute() { + void execute_() { this.command.execute(); } diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/CallbackAsynchronousSynchronizer.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/CallbackAsynchronousSynchronizer.java index 28eab58170..28c610d642 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/CallbackAsynchronousSynchronizer.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/CallbackAsynchronousSynchronizer.java @@ -104,8 +104,8 @@ public class CallbackAsynchronousSynchronizer } @Override - void execute() { - super.execute(); + void execute_() { + super.execute_(); // hmmm - we will notify listeners even when we our thread is "interrupted"; // that seems ok... ~bjv if (CallbackAsynchronousSynchronizer.this.synchronizeFlag.isFalse()) { diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/CallbackSynchronousSynchronizer.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/CallbackSynchronousSynchronizer.java index 22477627fa..ab101511ec 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/CallbackSynchronousSynchronizer.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/CallbackSynchronousSynchronizer.java @@ -70,8 +70,8 @@ public class CallbackSynchronousSynchronizer // ********** override ********** @Override - void execute() { - super.execute(); + void execute_() { + super.execute_(); if (this.state.getValue() != State.REPEAT) { // hmmm - we will notify listeners even when we are "stopped"; // that seems ok... ~bjv diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/Synchronizer.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/Synchronizer.java index 85f45af88d..7b5a459ec6 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/Synchronizer.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/Synchronizer.java @@ -23,12 +23,6 @@ import java.io.Serializable; * a single master thread that would control the synchronizer's lifecycle and * the {@link #synchronize()} method will be called multiple times, possibly from * multiple threads. - * <p> - * Provisional API: This interface is part of an interim API that is still - * under development and expected to change significantly before reaching - * stability. It is available at this early stage to solicit feedback from - * pioneering adopters on the understanding that any code that uses this API - * will almost certainly be broken (repeatedly) as the API evolves. */ public interface Synchronizer { diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/SynchronousSynchronizer.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/SynchronousSynchronizer.java index 71202f72ea..ea0c6090e9 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/SynchronousSynchronizer.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/synchronizers/SynchronousSynchronizer.java @@ -9,7 +9,10 @@ ******************************************************************************/ package org.eclipse.jpt.utility.internal.synchronizers; +import java.util.Vector; + import org.eclipse.jpt.utility.Command; +import org.eclipse.jpt.utility.internal.CompositeException; import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.SynchronizedObject; @@ -57,6 +60,11 @@ public class SynchronousSynchronizer STOPPING } + /** + * A list of the uncaught exceptions thrown by the command. + */ + final Vector<Throwable> exceptions = new Vector<Throwable>(); + // ********** construction ********** @@ -152,9 +160,21 @@ public class SynchronousSynchronizer } /** + * Execute the client-supplied command. Do not allow any unhandled + * exceptions to kill the thread. Store them up for later pain. + */ + private void execute() { + try { + this.execute_(); + } catch (Throwable ex) { + this.exceptions.add(ex); + } + } + + /** * By default, just execute the command. */ - void execute() { + void execute_() { this.command.execute(); } @@ -185,7 +205,9 @@ public class SynchronousSynchronizer } /** - * Set the flags so that no further synchronizations occur. + * Set the flags so that no further synchronizations occur. If any uncaught + * exceptions were thrown while the synchronization was executing, + * wrap them in a composite exception and throw the composite exception. */ public synchronized void stop() { switch (this.state.getValue()) { @@ -206,6 +228,12 @@ public class SynchronousSynchronizer default: throw this.buildIllegalStateException(); } + + if (this.exceptions.size() > 0) { + Throwable[] temp = this.exceptions.toArray(new Throwable[this.exceptions.size()]); + this.exceptions.clear(); + throw new CompositeException(temp); + } } /** |