Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbvosburgh2012-04-05 21:02:02 +0000
committerbvosburgh2012-04-05 21:02:02 +0000
commitab6dbade8a4502bddc3c1c786c0d6904b8c2d7dc (patch)
treef66ea2fce0c41c66a07aed40c8c9fe394313a44d /common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt
parent96a78271f51aa80ffdd8defa7525729aa1609913 (diff)
downloadwebtools.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')
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/CollectingExceptionHandler.java3
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/StackTrace.java106
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/AsynchronousRepeatingCommandWrapper.java25
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/command/RepeatingCommandWrapper.java28
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();
}

Back to the top