From 666164d5134678772e55f481bcf59b44e5680374 Mon Sep 17 00:00:00 2001 From: Cherian Mathew Date: Thu, 14 Aug 2014 10:38:05 +0000 Subject: [PATCH 1/1] New class for logging and dialog functionality --- .gitattributes | 1 + .../taxeditor/model/MessagingUtils.java | 439 ++++++++++++++++++ 2 files changed, 440 insertions(+) create mode 100644 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/MessagingUtils.java diff --git a/.gitattributes b/.gitattributes index 001ebc172..cc961909e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1263,6 +1263,7 @@ eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/IPartCon eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/ImageResources.java -text eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/LineSelection.java -text eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/MementoHelper.java -text +eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/MessagingUtils.java -text eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/MultiLanguageText.java -text eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/NameHelper.java -text eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/NomenclaturalCodeHelper.java -text diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/MessagingUtils.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/MessagingUtils.java new file mode 100644 index 000000000..8c7cc4d9d --- /dev/null +++ b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/MessagingUtils.java @@ -0,0 +1,439 @@ +package eu.etaxonomy.taxeditor.model; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.log4j.Logger; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +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.taxeditor.store.internal.TaxeditorStorePlugin; + +/** + * Utility class which handles all the messaging information generated by the + * Editor. + * + * This includes logging as well as dialogs. + * + * @author cmathew + * + */ +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)."; + + /** + * Gets the Log4J logger for a given class + * + * @param clazz + * a {@link java.lang.Class} object. + * @return a {@link org.apache.log4j.Logger} object. + */ + public static Logger getLog4JLogger(Class clazz) { + return Logger.getLogger(clazz); + } + + /** + * Logs details from a given Status object + * + * @param status + * a {@link org.eclipse.core.runtime.IStatus} object. + */ + private static void log(IStatus status) { + TaxeditorStorePlugin.getDefault().getLog().log(status); + } + + /** + * Logs a status object as information. + * + * @param status + * a {@link org.eclipse.core.runtime.IStatus} object. + */ + public static void info(IStatus status) { + log(status); + } + + /** + * Logs a string as information. + * + * @param message + * a {@link java.lang.String} object. + */ + public static void info(String message) { + IStatus status = new Status(IStatus.INFO, AbstractUtility.getPluginId(), message); + info(status); + } + + /** + * Logs an exception from a given source as a warning. + * + * @param source + * @param t + */ + public static void warn(Class source, Throwable t) { + IStatus status = new Status(IStatus.WARNING, AbstractUtility.getPluginId(), t.getMessage(), t); + MessagingUtils.getLog4JLogger(source).warn(t); + log(status); + } + + /** + * Logs a status object from a given source as a warning. + * + * @param source + * @param status + */ + public static void warn(Class source, IStatus status) { + MessagingUtils.getLog4JLogger(source).warn(status.getMessage(), status.getException()); + log(status); + } + + /** + * Logs a string from a given source as a warning. + * + * + * @param source + * a {@link java.lang.Class} object. + * @param message + * a {@link java.lang.String} object. + */ + public static void warn(Class source, String message) { + IStatus status = new Status(IStatus.WARNING, AbstractUtility.getPluginId(), message); + MessagingUtils.getLog4JLogger(source).warn(message); + log(status); + } + + /** + * Logs a status object from a given source as an error. + * + * + * @param source + * a {@link java.lang.Class} object. + * @param status + * a {@link org.eclipse.core.runtime.IStatus} object. + */ + public static void error(Class source, IStatus status) { + getLog4JLogger(source) + .error(status.getMessage(), status.getException()); + log(status); + } + + /** + * Logs a string and exception from a given source as an error. + * + * + * @param source + * a {@link java.lang.Class} object. + * @param message + * a {@link java.lang.String} object. + * @param t + * a {@link java.lang.Throwable} object. + */ + public static void error(Class source, String message, Throwable t) { + IStatus status = new Status(IStatus.ERROR, AbstractUtility.getPluginId(), message, t); + error(source, status); + } + + + + /** + * Logs an exception from a given source as an error. + * + * + * @param source + * a {@link java.lang.Class} object. + * @param t + * a {@link java.lang.Throwable} object. + */ + public static void error(Class source, Throwable t) { + error(source.getClass(), t.getMessage(), t); + } + + /** + * 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 status + * a {@link org.eclipse.core.runtime.IStatus} object. + */ + public static void errorDialog(final String title, + final Object source, + final String message, + final IStatus status) { + + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + CdmErrorDialog ced = new CdmErrorDialog(AbstractUtility.getShell(), title, message, status); + ced.open(); + Class clazz = source != null ? source + .getClass() : this.getClass(); + error(clazz, status); + } + }); + } + + /** + * Displays a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog}. + * + * @param title + * @param source + * @param message + * @param pluginId + * @param t + */ + public static void errorDialog(final String title, + final Object source, + final String message, + final String pluginId, + final Throwable t) { + // 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 status = new Status(IStatus.ERROR, + pluginId, + t.getMessage(), + new Exception(sw.toString())); + errorDialog(title, source, message, status); + } + + /** + * 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 status + * a {@link org.eclipse.core.runtime.IStatus} object. + */ + public static void errorDialog(final String title, + final Object source, + final String message, + final IStatus status, + final boolean showStackTrace) { + if(showStackTrace && status.getException() != null) { + errorDialog(title, source, status.getPlugin(), message, status.getException()); + } else { + errorDialog(title, source, message, status); + } + } + + + /** + * 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 status + * a {@link org.eclipse.core.runtime.IStatus} object. + */ + public static void errorDialog(final String title, final Object source, + final IStatus status) { + errorDialog(title, source, null, status); + } + + /** + * Displays a dialog for an exception occurring in an operation. + * + * This will be either a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog} in case of a + * security runtime exception or a warning {@link org.eclipse.jface.dialogs.MessageDialog} in + * case of any other exception. + * + * @param title + * a {@link java.lang.String} object. + * @param source + * a {@link java.lang.Object} object. + * @param status + * a {@link org.eclipse.core.runtime.IStatus} object. + */ + public static void operationDialog(final Object source, + final Exception ex, + final String operationlabel, + final String hint) { + + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + MultiStatus info = null; + String title = null; + + // FIXME cannot access TaxonomicEditorPlugin.PLUGIN_ID from here + // String PID = TaxonomicEditorPlugin.PLUGIN_ID; + String PID = "eu.etaxonomy.taxeditor.application"; + + // checking security exceptions for every operation + RuntimeException securityRuntimeException = SecurityExceptionUtils.findSecurityRuntimeException(ex); + + // in case of a security exception it is a warning, else it is an error + if(securityRuntimeException != null){ + title = "Your changes could not be saved!"; + 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), PID, ex); + + } + + + } + }); + } + + + + + /** + * Displays a question {@link org.eclipse.jface.dialogs.MessageDialog}. + * + * @param title + * a {@link java.lang.String} object. + * @param message + * a {@link java.lang.String} object. + * @return a boolean. + */ + public static boolean confirmDialog(String title, String message) { + return MessageDialog.openQuestion(AbstractUtility.getShell(), title, message); + } + + /** + * Displays a message {@link org.eclipse.jface.dialogs.MessageDialog}. + * + * @param title + * @param source + * @param message + */ + public static void messageDialog(final String title, final Object source, final String message) { + MessagingUtils.messageDialog(title, source, message, null); + } + + /** + * Displays an error {@link org.eclipse.jface.dialogs.MessageDialog}. + * + * @param title + * The dialogs title + * @param source + * The object where the warning was generated (used by log4j) + * @param message + * An informative String to be presented to the user + * @param title + * The dialogs title + * @param t + * a Throwable if one exists or null + */ + public static void messageDialog(final String title, final Object source, + final String message, final Throwable t) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + MessageDialog.openError(AbstractUtility.getShell(), title, message + getCauseRecursively(t)); + Class clazz = source != null ? source + .getClass() : this.getClass(); + error(clazz, message, t); + } + + private String getCauseRecursively(Throwable t) { + if(t == null){ + return ""; + } + + if(t.getCause() != null){ + return getCauseRecursively(t.getCause()); + }else{ + return String.format("\n\nException: %s\nMessage: %s", t.getClass().getSimpleName(), t.getMessage()); + } + + } + }); + } + + /** + * Displays a warning {@link org.eclipse.jface.dialogs.MessageDialog}. + * + * @param title + * @param termBase + * @param status + */ + public static void warningDialog(String title, Object source, + IStatus status) { + MessagingUtils.warningDialog(title, source, status.getMessage()); + } + + /** + * Displays a warning {@link org.eclipse.jface.dialogs.MessageDialog}. + * + * @param title + * The dialogs title + * @param source + * The object where the warning was generated (used by log4j) + * @param message + * An informative String to be presented to the user + */ + public static void warningDialog(final String title, final Object source, final String message) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + MessageDialog.openWarning(AbstractUtility.getShell(), title, message); + Class clazz = source != null ? source + .getClass() : AbstractUtility.class; + warn(clazz, message); + } + }); + } + + /** + * Displays an information {@link org.eclipse.jface.dialogs.MessageDialog}. + * + * @param title + * @param status + */ + public static void informationDialog(final String title, final IStatus status) { + MessagingUtils.informationDialog(title, status.getMessage()); + } + + /** + * Displays an information {@link org.eclipse.jface.dialogs.MessageDialog}. + * + * @param title + * a {@link java.lang.String} object. + * @param message + * a {@link java.lang.String} object. + */ + public static void informationDialog(final String title, + final String message) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + MessageDialog.openInformation(AbstractUtility.getShell(), title, message); + } + }); + } + + /** + * Open a message box that informs the user about unimplemented + * functionality. This method is for developer convenience. + * + * @param source + * a {@link java.lang.Object} object. + */ + public static void notImplementedMessage(Object source) { + warningDialog("Not yet implemented", source, + "This functionality is not yet implemented."); + } + +} -- 2.34.1