edu.mit.csail.sdg.alloy4.MailBug Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of alloy-core Show documentation
Show all versions of alloy-core Show documentation
The core of the Alloy tools
The newest version!
/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package edu.mit.csail.sdg.alloy4;
import java.awt.Color;
import java.awt.Dimension;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import org.alloytools.alloy.core.AlloyCore;
/**
* This class asks the user for permission to email a bug report when an
* uncaught exception occurs.
*/
public final class MailBug implements UncaughtExceptionHandler, Runnable {
/**
* The version number of the most recent Alloy4 (as queried from alloy.mit.edu);
* -1 if alloy.mit.edu has not replied yet.
*/
private static int latestAlloyVersion = -1;
/**
* The name of the most recent Alloy4 (as queried from alloy.mit.edu); "unknown"
* if alloy.mit.edu has not replied yet.
*/
private static String latestAlloyVersionName = "unknown";
/** The URL where the bug report should be sent. */
private static final String ALLOY_URL = "http://alloy.mit.edu/postbug4.php";
/**
* The URL where the current version info can be queried.
*/
private static final String ALLOY_NOW = "http://alloy.mit.edu/alloy4/download/alloy4.txt";
/**
* If alloy.mit.edu has replied, then return the latest Alloy build number, else
* return -1.
*/
public static int latestBuildNumber() {
synchronized (MailBug.class) {
return latestAlloyVersion;
}
}
/**
* If alloy.mit.edu has replied, then return the latest Alloy build name, else
* return "unknown"
*/
public static String latestBuildName() {
synchronized (MailBug.class) {
return latestAlloyVersionName;
}
}
/** Construct a new MailBug object. */
private MailBug() {}
/**
* Setup the uncaught-exception-handler and use a separate thread to query
* alloy.mit.edu for latest version number.
*/
public static void setup() {
if (AlloyCore.isDebug())
return;
if (Thread.getDefaultUncaughtExceptionHandler() != null)
return;
MailBug x = new MailBug();
Thread.setDefaultUncaughtExceptionHandler(x);
new Thread(x).start();
}
/**
* This method concatenates a Throwable's message and stack trace and all its
* causes into a single String.
*/
public static String dump(Throwable ex) {
StringBuilder sb = new StringBuilder();
while (ex != null) {
sb.append(ex.getClass()).append(": ").append(ex.getMessage()).append('\n');
StackTraceElement[] trace = ex.getStackTrace();
if (trace != null)
for (int n = trace.length, i = 0; i < n; i++)
sb.append(trace[i]).append('\n');
ex = ex.getCause();
if (ex != null)
sb.append("caused by...\n");
}
return sb.toString().trim();
}
/**
* This method returns true if the exception appears to be a Sun Java GUI bug.
*/
private static boolean isGUI(Throwable ex) {
// If the root of the stack trace is within Java framework itself,
// and no where is Alloy, Kodkod, or SAT4J anywhere along the trace,
// then it's almost *always* a Sun Java GUI bug from what we've seen.
// And it's better to ignore it rather than kill the file that the user
// is editing.
while (ex != null) {
StackTraceElement[] trace = ex.getStackTrace();
for (int n = (trace == null ? 0 : trace.length), i = 0; i < n; i++) {
String name = trace[i].getClassName();
if (!name.startsWith("java.") && !name.startsWith("javax.") && !name.startsWith("sun."))
return false;
}
ex = ex.getCause();
}
return true;
}
/** This method prepares the crash report. */
private static String prepareCrashReport(Thread thread, Throwable ex, String email, String problem) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.printf("Alloy Analyzer %s crash report (Build Date = %s) (Commit = %s)\n", Version.version(), Version.commit);
pw.printf("\n========================= Email ============================\n%s\n", Util.convertLineBreak(email).trim());
pw.printf("\n========================= Problem ==========================\n%s\n", Util.convertLineBreak(problem).trim());
pw.printf("\n========================= Thread Name ======================\n%s\n", thread.getName().trim());
if (ex != null)
pw.printf("\n========================= Stack Trace ======================\n%s\n", dump(ex));
pw.printf("\n========================= Preferences ======================\n");
try {
for (String key : Preferences.userNodeForPackage(Util.class).keys()) {
String value = Preferences.userNodeForPackage(Util.class).get(key, "");
pw.printf("%s = %s\n", key.trim(), value.trim());
}
} catch (BackingStoreException bse) {
pw.printf("BackingStoreException occurred: %s\n", bse.toString().trim());
}
pw.printf("\n========================= System Properties ================\n");
pw.println("Runtime.freeMemory() = " + Runtime.getRuntime().freeMemory());
pw.println("nRuntime.totalMemory() = " + Runtime.getRuntime().totalMemory());
for (Map.Entry