/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.ui.internal.statushandlers; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.net.URLEncoder; import java.util.Random; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProduct; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.statushandlers.IStatusAdapterConstants; import org.eclipse.ui.statushandlers.StatusAdapter; public class StatusDetails { private final StatusAdapter statusAdapter; private String detailsText = null; public StatusDetails(StatusAdapter statusAdapter) { this.statusAdapter = statusAdapter; } public StatusAdapter getStatusAdapter() { return statusAdapter; } public Image getImage() { int severity = statusAdapter.getStatus().getSeverity(); int iconId; if ((severity & IStatus.ERROR) != 0) { iconId = SWT.ICON_ERROR; } else if ((severity & IStatus.WARNING) != 0) { iconId = SWT.ICON_WARNING; } else { iconId = SWT.ICON_INFORMATION; } return Display.getCurrent().getSystemImage(iconId); } public String getMessage() { IStatus status = statusAdapter.getStatus(); String message = status.getMessage(); if (message != null && !"".equals(message)) //$NON-NLS-1$ return message; Throwable exception = getRootCause(status.getException()); if (exception != null) return NLS .bind(StatusHandlerMessages.StatusDetails_ErrorMessage_with_RootCauseClassName_and_RootCauseMessage, exception.getClass().getName(), exception.getLocalizedMessage()); return StatusHandlerMessages.StatusDetails_SimpleErrorMessage; } public String getFullText() { if (detailsText == null) { detailsText = buildDetailsText(statusAdapter); } return detailsText; } public String buildMailingURL() { String caseId = generateCaseId(); String subject = String.format( "XMind Runtime Error Report (Case ID: %s)", //$NON-NLS-1$ caseId); return String.format( "mailto:support@xmind.net?subject=%s&body=%s", //$NON-NLS-1$ urlEncode(subject), urlEncode(System.getProperty("line.separator") //$NON-NLS-1$ + getFullText())); } private static String buildDetailsText(StatusAdapter statusAdapter) { ByteArrayOutputStream out = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(out); IStatus status = statusAdapter.getStatus(); String message = status.getMessage(); Throwable exception = status.getException(); Long timestamp = (Long) statusAdapter .getProperty(IStatusAdapterConstants.TIMESTAMP_PROPERTY); if (message != null) { ps.println(message); ps.println(); } if (exception != null) { exception.printStackTrace(ps); } ps.println(); ps.printf("Severity: %s", toSeverityString(status.getSeverity())); //$NON-NLS-1$ ps.println(); ps.printf("Plug-in ID: %s", status.getPlugin()); //$NON-NLS-1$ ps.println(); ps.printf("Code: %s", status.getCode()); //$NON-NLS-1$ ps.println(); ps.println(); ps.println("== Environment =="); //$NON-NLS-1$ ps.printf("Time: %1$tF %1$tT", //$NON-NLS-1$ timestamp); ps.println(); String application = System.getProperty("eclipse.application"); //$NON-NLS-1$ if (application == null || "".equals(application)) { //$NON-NLS-1$ IProduct product = Platform.getProduct(); if (product != null) { application = product.getApplication(); } } if ("org.xmind.cathy.application".equals(application)) { //$NON-NLS-1$ printp(ps, "XMind Distribution Pack: %s", //$NON-NLS-1$ "org.xmind.product.distribution.id"); //$NON-NLS-1$ } else { ps.println("XMind Installed as Plugins"); //$NON-NLS-1$ } printp(ps, "XMind Build ID: %s", "org.xmind.product.buildid"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, "Operating System: %s %s (%s)", //$NON-NLS-1$ "os.name", "os.version", "os.arch"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ printp(ps, "Platform: %s.%s.%s", //$NON-NLS-1$ "osgi.os", "osgi.ws", "osgi.arch"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ printp(ps, "Language: %s", "user.language"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, "Country: %s", "user.country"); //$NON-NLS-1$ //$NON-NLS-2$ ps.println(); ps.println("== Product =="); //$NON-NLS-1$ printp(ps, "Product ID: %s", "eclipse.product"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, "Application ID: %s", "eclipse.application"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, "Launcher: %s", "eclipse.launcher.name"); //$NON-NLS-1$ //$NON-NLS-2$ ps.println(); printp(ps, "Command Line Arguments: %s", "eclipse.commands"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, "VM Arguments: %s", "eclipse.vmargs"); //$NON-NLS-1$ //$NON-NLS-2$ ps.println(); ps.println("== Java Properties =="); //$NON-NLS-1$ printp(ps, "Java Version: %s", "java.version"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, "Java Vendor: %s", "java.vendor"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, "Java Runtime: %s", "java.runtime.name"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, " Version: %s", "java.runtime.version"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, "Java VM: %s", "java.vm.name"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, " Version: %s", "java.vm.version"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, " Vendor: %s", "java.vm.vendor"); //$NON-NLS-1$ //$NON-NLS-2$ printp(ps, " Info: %s", "java.vm.info"); //$NON-NLS-1$ //$NON-NLS-2$ ps.close(); try { out.close(); } catch (IOException e) { } // Replace user name to protect privacy: String text = out.toString(); String userName = System.getProperty("user.name"); //$NON-NLS-1$ if (userName != null && !"".equals(userName.trim())) { //$NON-NLS-1$ text = text.replace(userName, "USERNAME"); //$NON-NLS-1$ } return text; } private static void printp(PrintStream ps, String format, String... keys) { Object[] values = new Object[keys.length]; for (int i = 0; i < keys.length; i++) { String key = keys[i]; String value = getSysProp(key); if (value.indexOf("\n") >= 0 || value.indexOf("\r") >= 0) { //$NON-NLS-1$ //$NON-NLS-2$ value = value.replaceAll("\r\n|\r|\n", //$NON-NLS-1$ System.getProperty("line.separator") + " "); //$NON-NLS-1$ //$NON-NLS-2$ } values[i] = value; } ps.printf(format, values); ps.println(); } private static String getSysProp(String key) { String value = System.getProperty(key); return value == null ? "" : value; //$NON-NLS-1$ } private static String urlEncode(String string) { try { return URLEncoder.encode(string, "UTF-8") //$NON-NLS-1$ .replace("+", "%20"); //$NON-NLS-1$ //$NON-NLS-2$ } catch (UnsupportedEncodingException e) { return string; } } private static String generateCaseId() { return Integer.toString(new Random().nextInt(Integer.MAX_VALUE), 36) .toUpperCase(); } private static String toSeverityString(int s) { if ((s & IStatus.ERROR) != 0) return "error"; //$NON-NLS-1$ if ((s & IStatus.WARNING) != 0) return "warning"; //$NON-NLS-1$ if ((s & IStatus.INFO) != 0) return "info"; //$NON-NLS-1$ if ((s & IStatus.CANCEL) != 0) return "cancel"; //$NON-NLS-1$ return "ok"; //$NON-NLS-1$ } public static Throwable getRootCause(Throwable exception) { if (exception == null) return null; if (exception instanceof InvocationTargetException) return getRootCause(((InvocationTargetException) exception) .getCause()); if (exception instanceof CoreException) { Throwable cause = ((CoreException) exception).getStatus() .getException(); if (cause != null) return getRootCause(cause); } return exception; } }