import java.util.ArrayList;
import java.util.List;
+import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
-import eu.etaxonomy.cdm.persistence.hibernate.permission.SecurityExceptionUtils;
+import eu.etaxonomy.cdm.common.CdmUtils;
+import eu.etaxonomy.cdm.config.ICdmSource;
+import eu.etaxonomy.cdm.test.integration.SecurityExceptionUtils;
+import eu.etaxonomy.taxeditor.remoting.source.CdmRemoteSource;
+import eu.etaxonomy.taxeditor.store.CdmStore;
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
/**
public class MessagingUtils {
public final static String UNEXPECTED_ERROR_MESSAGE = "This is an unexpected error.";
public final static String CONTACT_MESSAGE = System.getProperty("line.separator") + "Please contact EDIT Support (EditSupport@bgbm.org) with the error trace below (click on the 'Details' button).";
-
+ public final static String DEFAULT_MESSAGE = "Error thrown but no associated message";
+ public final static String CONNECTION_FAILURE_MESSAGE = "The connection to the remote server has been broken";
+ public final static String REMOTE_ACCESS_FAILURE_MESSAGE = "Maybe the server is currently not available. If the problem persists please contact the server admin with the error trace below.";
+ public static final String WIDGET_IS_DISPOSED_MESSAGE = "A widget was called, which was already disposed";
+ public static final String ACCESS_DENIED = "The connection to the server could not be established because the access was denied.";
/**
* Gets the Log4J logger for a given class
*
error(source.getClass(), t.getMessage(), t);
}
+
+
+ /**
+ * Returns a list of strings, providing info on,
+ * - login
+ * - editor version
+ * - server (address + source name)
+ * - db schema version
+ *
+ * @return
+ */
+ public static List<String> getContextInfo() {
+ List<String> contextInfo = new ArrayList<String>();
+ String name = "";
+ String contextPath = "";
+ String schemaVersion = "";
+ String server = "";
+ String version = "";
+ String login = "";
+ try {
+ version = Platform.getBundle("eu.etaxonomy.taxeditor.application").getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION);
+
+ ICdmSource activeCdmSource = CdmStore.getActiveCdmSource();
+ if(activeCdmSource != null ) {
+ login = CdmStore.getLoginManager().getAuthenticatedUser().getUsername();
+ name = activeCdmSource.getName();
+ schemaVersion = activeCdmSource.getDbSchemaVersion();
+ server = activeCdmSource.getServer();
+ if(activeCdmSource instanceof CdmRemoteSource){
+ contextPath = ((CdmRemoteSource) activeCdmSource).getContextPath();
+ if (contextPath != null && contextPath.startsWith("cdmserver/")){
+ contextPath = contextPath.substring("cdmserver/".length());
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ // Nothing to do
+ }
+ contextInfo.add("login : " + login);
+ contextInfo.add("editor version : " + version);
+ contextInfo.add("server : " + server + " (" + name + ")" + (CdmUtils.isNotBlank(contextPath)?" / "+contextPath:""));
+ contextInfo.add("schema version : " + schemaVersion);
+ contextInfo.add("os : " + System.getProperty("os.name")+" "+System.getProperty("os.version")+" "+System.getProperty("os.arch"));
+ contextInfo.add("java : "+System.getProperty("java.version"));
+
+ return contextInfo;
+ }
+
+ public static String getStackTraceAndContextInfo(Throwable t, List<String> contextInfo) {
+ StringBuffer stackTraceAndContextInfo = new StringBuffer();
+ Throwable throwable = t;
+
+ for(String infoItem : contextInfo) {
+ stackTraceAndContextInfo.append(infoItem + System.getProperty("line.separator"));
+ }
+
+ StringWriter sw = new StringWriter();
+
+ if(throwable == null) {
+ throwable = getDefaultThrowable();
+ }
+ throwable.printStackTrace(new PrintWriter(sw));
+
+ stackTraceAndContextInfo.append(sw.toString());
+
+ return stackTraceAndContextInfo.toString();
+ }
+
+ public static String getContextInfo(List<String> contextInfo) {
+ StringBuffer scontextInfoStringBuffer = new StringBuffer();
+
+
+ for(String infoItem : contextInfo) {
+ scontextInfoStringBuffer.append(infoItem + System.getProperty("line.separator"));
+ }
+
+
+
+ return scontextInfoStringBuffer.toString();
+ }
+
+ private static Throwable getDefaultThrowable() {
+ return new Throwable("Error thrown but no associated exception");
+ }
+
+
+
/**
* Displays a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog}.
*
* @param title
- * a {@link java.lang.String} object.
* @param source
- * a {@link java.lang.Object} object.
+ * @param t
+ * @param contextInfo
+ * @param message
* @param status
- * a {@link org.eclipse.core.runtime.IStatus} object.
*/
private static void errorDialog(final String title,
final Object source,
+ final Throwable t,
+ final List<String> contextInfo,
final String message,
- final IStatus status) {
+ final MultiStatus status,
+ final boolean showReason) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
- CdmErrorDialog ced = new CdmErrorDialog(AbstractUtility.getShell(), title, message, status);
+ String stackTraceWithContext = getStackTraceAndContextInfo(t, contextInfo);
+ CdmErrorDialog ced = new CdmErrorDialog(AbstractUtility.getShell(), title, message, status, stackTraceWithContext, showReason);
ced.open();
Class<? extends Object> clazz = source != null ? source.getClass() : this.getClass();
- error(clazz, status);
- }
- });
- }
-
- private static void errorDialog(final String title,
- final Object source,
- final Throwable t,
- final MultiStatus status) {
- Display.getDefault().asyncExec(new Runnable() {
- @Override
- public void run() {
- CdmErrorDialog ced = new CdmErrorDialog(AbstractUtility.getShell(), title, t.getMessage(), status);
- ced.open();
- Class<? extends Object> clazz = source != null ? source.getClass() : this.getClass();
-
- // Usually the status contains only the first line of the stack trace.
- // For the unexpected messages we need the entire stack trace so we
- // create a new status with the entire stacktrace
- StringWriter sw = new StringWriter();
- t.printStackTrace(new PrintWriter(sw));
IStatus singleStatus = new Status(IStatus.ERROR,
status.getPlugin(),
- status.getMessage(),
- new Exception(sw.toString()));
+ message,
+ new Exception(stackTraceWithContext));
error(clazz, singleStatus);
}
});
}
+ public static void errorDialog(final String title,
+ final Object source,
+ final String message,
+ final String pluginId,
+ final Throwable t,
+ boolean addContactMesg) {
+ errorDialog(title, source, message, pluginId, t, addContactMesg, true);
+
+ }
/**
* Displays a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog}.
*
final String message,
final String pluginId,
final Throwable t,
- boolean addContactMesg) {
-
+ boolean addContactMesg,
+ boolean showReason) {
+ Throwable throwable = t;
StringBuffer sbStackTrace = new StringBuffer();
// We need to build a MultiStatus object since the simple
// idea of writing out the stack trace as a single string
// leads to a single line on windows
List<Status> childStatuses = new ArrayList<Status>();
- for (StackTraceElement ste : t.getStackTrace()) {
- // build & add status
- childStatuses.add(new Status(IStatus.ERROR, pluginId, "at " + ste.toString()));
+
+ // add context info
+ List<String> contextInfo = getContextInfo();
+ for(String infoItem : contextInfo) {
+ childStatuses.add(new Status(IStatus.ERROR, pluginId, infoItem));
+ }
+
+ if(throwable == null) {
+ throwable = getDefaultThrowable();
}
- // build message with contact info
+ int thCount = 0;
+ int maxTraces = 4;
+
+ for(Throwable th : ExceptionUtils.getThrowables(throwable)) {
+ // add main exception
+ if(thCount == 0) {
+ for (StackTraceElement ste : th.getStackTrace()) {
+ childStatuses.add(new Status(IStatus.ERROR, pluginId, " at " + ste.toString()));
+ }
+ } else {
+ // add recursive causes
+ if(th != null) {
+ childStatuses.add(new Status(IStatus.ERROR, pluginId, ""));
+ String msg = th.toString();
+ childStatuses.add(new Status(IStatus.ERROR, pluginId, "Caused by : " + msg));
+ int traceCount = 0;
+ for (StackTraceElement ste : th.getStackTrace()) {
+ // add only pre-defined number of trace elements
+ if(traceCount > maxTraces) {
+ childStatuses.add(new Status(IStatus.ERROR, pluginId, " ...."));
+ break;
+ }
+ // build & add status
+ childStatuses.add(new Status(IStatus.ERROR, pluginId, " at " + ste.toString()));
+ traceCount++;
+ }
+ }
+ }
+ thCount++;
+ }
String finalMessage = message;
if(finalMessage == null || finalMessage.isEmpty()) {
- finalMessage = "";
+ finalMessage = DEFAULT_MESSAGE;
}
if(addContactMesg) {
+ // add edit support contact info to message
finalMessage += MessagingUtils.CONTACT_MESSAGE;
}
MultiStatus ms = new MultiStatus(pluginId,
IStatus.ERROR,
childStatuses.toArray(new Status[] {}),
- finalMessage,
- t);
+ throwable.toString(),
+ throwable);
- errorDialog(title, source, t, ms);
+ errorDialog(title, source, throwable, contextInfo, finalMessage, ms, showReason);
}
-
/**
* Displays a dialog for an exception occurring in an operation.
*
warningDialog(title, source, String.format("You are missing sufficient permissions for the operation \"%s\". %s", operationlabel, hint));
} else {
title = "Error executing operation";
- errorDialog(title, source, String.format("An error occured while executing %s. %s", operationlabel, hint), pluginId, ex, true);
+ errorDialog(title, source, String.format("An error occurred while executing %s. %s", operationlabel, hint), pluginId, ex, true);
}
return MessageDialog.openQuestion(AbstractUtility.getShell(), title, message);
}
+ public static int confirmDialog(String title, String message, String...labels){
+ MessageDialog dialog =new MessageDialog(AbstractUtility.getShell(), title, null, message, MessageDialog.QUESTION,labels, 0);
+ int result = dialog.open();
+ return result;
+ }
+
/**
* Displays a message {@link org.eclipse.jface.dialogs.MessageDialog}.
*
MessagingUtils.warningDialog(title, source, status.getMessage());
}
+ /**
+ * Standard warning dialog for the case when the application is not yet connected to the datasource
+ *
+ * @param source
+ */
+ public static void noDataSourceWarningDialog(Object source) {
+ MessagingUtils
+ .warningDialog(
+ "Application is not connected to a datastore",
+ source,
+ "The requested operation is only available when "
+ + "connected to a datasource. You may choose a datasource to connect to or create a new one in the datasource view.");
+ }
+
+ /**
+ * Standard warning dialog for the case when the datasource is not available
+ *
+ * @param source
+ */
+ public static void dataSourceNotAvailableWarningDialog(Object source) {
+ MessagingUtils
+ .warningDialog(
+ "The datasource is not available",
+ source,
+ "The editor is not connected to a datasource. Maybe the datasource is not available.");
+ }
+
+
/**
* Displays a warning {@link org.eclipse.jface.dialogs.MessageDialog}.
*