diff options
author | bvosburgh | 2012-04-05 21:02:02 +0000 |
---|---|---|
committer | bvosburgh | 2012-04-05 21:02:02 +0000 |
commit | ab6dbade8a4502bddc3c1c786c0d6904b8c2d7dc (patch) | |
tree | f66ea2fce0c41c66a07aed40c8c9fe394313a44d /common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt | |
parent | 96a78271f51aa80ffdd8defa7525729aa1609913 (diff) | |
download | webtools.dali-ab6dbade8a4502bddc3c1c786c0d6904b8c2d7dc.tar.gz webtools.dali-ab6dbade8a4502bddc3c1c786c0d6904b8c2d7dc.tar.xz webtools.dali-ab6dbade8a4502bddc3c1c786c0d6904b8c2d7dc.zip |
capture sync and update stack traces for debugging
Diffstat (limited to 'common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt')
4 files changed, 152 insertions, 10 deletions
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/CollectingExceptionHandler.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/CollectingExceptionHandler.java index 93ac401f0a..55f90eb25c 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/CollectingExceptionHandler.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/CollectingExceptionHandler.java @@ -11,7 +11,6 @@ package org.eclipse.jpt.common.utility.internal; import java.util.Vector; import org.eclipse.jpt.common.utility.ExceptionHandler; -import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable; import org.eclipse.jpt.common.utility.internal.iterables.SnapshotCloneIterable; /** @@ -32,7 +31,7 @@ public class CollectingExceptionHandler * Return the current list of exceptions handled by the handler so far. */ public Iterable<Throwable> getExceptions() { - return new LiveCloneIterable<Throwable>(this.exceptions); + return new SnapshotCloneIterable<Throwable>(this.exceptions); } /** diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/StackTrace.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/StackTrace.java new file mode 100644 index 0000000000..05a141e3af --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/StackTrace.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2012 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.common.utility.internal; + +import java.io.IOException; +import java.io.Serializable; + +/** + * Container for holding and printing the {@StackTraceElement stack trace + * elements} produced by a thread or exception. + * + * @see Thread#getStackTrace() + * @see Throwable#getStackTrace() + */ +public class StackTrace + implements Serializable +{ + private final StackTraceElement[] elements; + private volatile String string; + private static final long serialVersionUID = 1L; + + + public StackTrace() { + super(); + this.elements = this.buildElements(); + } + + /** + * Strip off all the elements associated with this class and {@link Thread}. + */ + private StackTraceElement[] buildElements() { + StackTraceElement[] result = Thread.currentThread().getStackTrace(); + int len = result.length; + if (len == 0) { + return result; + } + + String className = this.getClass().getName(); + boolean found = false; + int i = 0; + while (i < len) { + if (result[i].getClassName().equals(className)) { + found = true; + } else { + if (found) { + break; + } + } + i++; + } + return found ? ArrayTools.subArray(result, i, len) : result; + } + + /** + * Append the stack trace to the specified stream. + */ + public void appendTo(Appendable stream) throws IOException { + this.appendTo(stream, null); + } + + /** + * Append the stack trace to the specified stream, prefixing each line + * with the specified prefix. + */ + public void appendTo(Appendable stream, String prefix) throws IOException { + for (StackTraceElement element : this.elements) { + if (prefix != null) { + stream.append(prefix); + } + stream.append(String.valueOf(element)).append(StringTools.CR); + } + } + + @Override + public String toString() { + return this.getString(); + } + + private String getString() { + if (this.string == null) { + synchronized (this) { + if (this.string == null) { + this.string = this.buildString(); + } + } + } + return this.string; + } + + private String buildString() { + StringBuffer sb = new StringBuffer(1000); + try { + this.appendTo(sb); + } catch (IOException ex) { + throw new RuntimeException(ex); // should not happen with a StringBuffer + } + return sb.toString(); + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/AsynchronousRepeatingCommandWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/AsynchronousRepeatingCommandWrapper.java index 76331d4728..7baa423bb8 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/AsynchronousRepeatingCommandWrapper.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/AsynchronousRepeatingCommandWrapper.java @@ -9,12 +9,14 @@ ******************************************************************************/ package org.eclipse.jpt.common.utility.internal.command; +import java.util.ArrayList; import java.util.concurrent.ThreadFactory; import org.eclipse.jpt.common.utility.ExceptionHandler; import org.eclipse.jpt.common.utility.command.Command; import org.eclipse.jpt.common.utility.command.RepeatingCommand; import org.eclipse.jpt.common.utility.internal.ConsumerThreadCoordinator; import org.eclipse.jpt.common.utility.internal.SimpleThreadFactory; +import org.eclipse.jpt.common.utility.internal.StackTrace; import org.eclipse.jpt.common.utility.internal.StringTools; import org.eclipse.jpt.common.utility.internal.SynchronizedBoolean; @@ -22,10 +24,6 @@ import org.eclipse.jpt.common.utility.internal.SynchronizedBoolean; * This repeating command will perform a client-supplied command in a separate * thread, allowing calls to {@link org.eclipse.jpt.common.utility.command.Command#execute()} * to return immediately. - * <p> - * <strong>NB:</strong> The client-supplied command should handle any exceptions - * appropriately (e.g. log the exception and return gracefully so the thread - * can continue the execution process). */ public class AsynchronousRepeatingCommandWrapper implements RepeatingCommand @@ -43,6 +41,15 @@ public class AsynchronousRepeatingCommandWrapper */ private final ConsumerThreadCoordinator consumerThreadCoordinator; + /** + * List of stack traces for each (repeating) invocation of the command, + * starting with the initial invocation. The list is cleared with each + * initial invocation of the command. + */ + private final ArrayList<StackTrace> stackTraces = DEBUG ? new ArrayList<StackTrace>() : null; + // see AsynchronousRepeatingCommandWrapperTests.testDEBUG() + private static final boolean DEBUG = false; + // ********** construction ********** @@ -133,7 +140,15 @@ public class AsynchronousRepeatingCommandWrapper * </ul> */ public void execute() { - this.executeFlag.setTrue(); + synchronized (this.executeFlag) { + if (DEBUG) { + if (this.executeFlag.isFalse()) { + this.stackTraces.clear(); + } + this.stackTraces.add(new StackTrace()); + } + this.executeFlag.setTrue(); + } } /** diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/RepeatingCommandWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/RepeatingCommandWrapper.java index be9e4e127e..fcdb26b33b 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/RepeatingCommandWrapper.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/RepeatingCommandWrapper.java @@ -9,10 +9,12 @@ ******************************************************************************/ package org.eclipse.jpt.common.utility.internal.command; +import java.util.ArrayList; import org.eclipse.jpt.common.utility.ExceptionHandler; import org.eclipse.jpt.common.utility.command.Command; import org.eclipse.jpt.common.utility.command.CommandExecutor; import org.eclipse.jpt.common.utility.command.RepeatingCommand; +import org.eclipse.jpt.common.utility.internal.StackTrace; import org.eclipse.jpt.common.utility.internal.StringTools; /** @@ -57,6 +59,15 @@ public class RepeatingCommandWrapper */ final RepeatingCommandState state; + /** + * List of stack traces for each (repeating) invocation of the command, + * starting with the initial invocation. The list is cleared with each + * initial invocation of the command. + */ + private final ArrayList<StackTrace> stackTraces = DEBUG ? new ArrayList<StackTrace>() : null; + // see RepeatingCommandWrapperTests.testDEBUG() + private static final boolean DEBUG = false; + // ********** construction ********** @@ -107,13 +118,24 @@ public class RepeatingCommandWrapper * It is possible to come back here if the wrapped command recurses * to the client and triggers another execution. */ - // pretty sure no need for this method to be 'synchronized' - public void execute() { + public synchronized void execute() { if (this.state.isReadyToStartExecutionCycle()) { - this.startCommandExecutor.execute(this.startCommand); + if (DEBUG) { + this.stackTraces.clear(); + this.stackTraces.add(new StackTrace()); + } + this.executeStartCommand(); + } else { + if (DEBUG) { + this.stackTraces.add(new StackTrace()); + } } } + /* private protected */ void executeStartCommand() { + this.startCommandExecutor.execute(this.startCommand); + } + public void stop() throws InterruptedException { this.state.stop(); } |