1 package eu
.etaxonomy
.taxeditor
.model
;
3 import java
.io
.PrintWriter
;
4 import java
.io
.StringWriter
;
5 import java
.util
.ArrayList
;
8 import org
.apache
.log4j
.Logger
;
9 import org
.eclipse
.core
.runtime
.IStatus
;
10 import org
.eclipse
.core
.runtime
.MultiStatus
;
11 import org
.eclipse
.core
.runtime
.Platform
;
12 import org
.eclipse
.core
.runtime
.Status
;
13 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
14 import org
.eclipse
.swt
.widgets
.Display
;
16 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.SecurityExceptionUtils
;
17 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
18 import eu
.etaxonomy
.taxeditor
.store
.internal
.TaxeditorStorePlugin
;
21 * Utility class which handles all the messaging information generated by the
24 * This includes logging as well as dialogs.
29 public class MessagingUtils
{
30 public final static String UNEXPECTED_ERROR_MESSAGE
= "This is an unexpected error.";
31 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).";
32 public final static String DEFAULT_MESSAGE
= "Error thrown but no associated message";
35 * Gets the Log4J logger for a given class
38 * a {@link java.lang.Class} object.
39 * @return a {@link org.apache.log4j.Logger} object.
41 public static Logger
getLog4JLogger(Class clazz
) {
42 return Logger
.getLogger(clazz
);
46 * Logs details from a given Status object
49 * a {@link org.eclipse.core.runtime.IStatus} object.
51 private static void log(IStatus status
) {
52 TaxeditorStorePlugin
.getDefault().getLog().log(status
);
56 * Logs a status object as information.
59 * a {@link org.eclipse.core.runtime.IStatus} object.
61 public static void info(IStatus status
) {
66 * Logs a string as information.
69 * a {@link java.lang.String} object.
71 public static void info(String message
) {
72 IStatus status
= new Status(IStatus
.INFO
, AbstractUtility
.getPluginId(), message
);
77 * Logs an exception from a given source as a warning.
82 public static void warn(Class source
, Throwable t
) {
83 IStatus status
= new Status(IStatus
.WARNING
, AbstractUtility
.getPluginId(), t
.getMessage(), t
);
84 MessagingUtils
.getLog4JLogger(source
).warn(t
);
89 * Logs a status object from a given source as a warning.
94 public static void warn(Class source
, IStatus status
) {
95 MessagingUtils
.getLog4JLogger(source
).warn(status
.getMessage(), status
.getException());
100 * Logs a string from a given source as a warning.
104 * a {@link java.lang.Class} object.
106 * a {@link java.lang.String} object.
108 public static void warn(Class source
, String message
) {
109 IStatus status
= new Status(IStatus
.WARNING
, AbstractUtility
.getPluginId(), message
);
110 MessagingUtils
.getLog4JLogger(source
).warn(message
);
115 * Logs a status object from a given source as an error.
119 * a {@link java.lang.Class} object.
121 * a {@link org.eclipse.core.runtime.IStatus} object.
123 public static void error(Class source
, IStatus status
) {
124 getLog4JLogger(source
)
125 .error(status
.getMessage(), status
.getException());
130 * Logs a string and exception from a given source as an error.
134 * a {@link java.lang.Class} object.
136 * a {@link java.lang.String} object.
138 * a {@link java.lang.Throwable} object.
140 public static void error(Class source
, String message
, Throwable t
) {
141 IStatus status
= new Status(IStatus
.ERROR
, AbstractUtility
.getPluginId(), message
, t
);
142 error(source
, status
);
148 * Logs an exception from a given source as an error.
152 * a {@link java.lang.Class} object.
154 * a {@link java.lang.Throwable} object.
156 public static void error(Class source
, Throwable t
) {
157 error(source
.getClass(), t
.getMessage(), t
);
163 * Returns a list of strings, providing info on,
166 * - server (address + source name)
167 * - db schema version
171 public static List
<String
> getContextInfo() {
172 List
<String
> contextInfo
= new ArrayList
<String
>();
174 String schemaVersion
= "";
179 version
= Platform
.getBundle("eu.etaxonomy.taxeditor.application").getHeaders().get(org
.osgi
.framework
.Constants
.BUNDLE_VERSION
);
181 if(CdmStore
.getActiveCdmSource() != null ) {
182 login
= CdmStore
.getLoginManager().getAuthenticatedUser().getUsername();
183 name
= CdmStore
.getActiveCdmSource().getName();
184 schemaVersion
= CdmStore
.getActiveCdmSource().getDbSchemaVersion();
185 server
= CdmStore
.getActiveCdmSource().getServer();
188 } catch (Exception e
) {
191 contextInfo
.add("login : " + login
);
192 contextInfo
.add("editor version : " + version
);
193 contextInfo
.add("server : " + server
+ " / " + name
);
194 contextInfo
.add("schema version : " + schemaVersion
);
199 public static String
getStackTraceAndContextInfo(Throwable t
, List
<String
> contextInfo
) {
200 StringBuffer stackTraceAndContextInfo
= new StringBuffer();
201 Throwable throwable
= t
;
203 for(String infoItem
: contextInfo
) {
204 stackTraceAndContextInfo
.append(infoItem
+ System
.getProperty("line.separator"));
207 StringWriter sw
= new StringWriter();
209 if(throwable
== null) {
210 throwable
= getDefaultThrowable();
212 throwable
.printStackTrace(new PrintWriter(sw
));
214 stackTraceAndContextInfo
.append(sw
.toString());
216 return stackTraceAndContextInfo
.toString();
219 private static Throwable
getDefaultThrowable() {
220 return new Throwable("Error thrown but no associated exception");
226 * Displays a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog}.
235 private static void errorDialog(final String title
,
238 final List
<String
> contextInfo
,
239 final String message
,
240 final MultiStatus status
) {
242 Display
.getDefault().asyncExec(new Runnable() {
246 String stackTraceWithContext
= getStackTraceAndContextInfo(t
, contextInfo
);
247 CdmErrorDialog ced
= new CdmErrorDialog(AbstractUtility
.getShell(), title
, message
, status
, stackTraceWithContext
);
249 Class
<?
extends Object
> clazz
= source
!= null ? source
.getClass() : this.getClass();
252 IStatus singleStatus
= new Status(IStatus
.ERROR
,
255 new Exception(stackTraceWithContext
));
257 error(clazz
, singleStatus
);
263 * Displays a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog}.
271 public static void errorDialog(final String title
,
273 final String message
,
274 final String pluginId
,
276 boolean addContactMesg
) {
278 Throwable throwable
= t
;
279 StringBuffer sbStackTrace
= new StringBuffer();
281 // We need to build a MultiStatus object since the simple
282 // idea of writing out the stack trace as a single string
283 // leads to a single line on windows
284 List
<Status
> childStatuses
= new ArrayList
<Status
>();
287 List
<String
> contextInfo
= getContextInfo();
288 for(String infoItem
: contextInfo
) {
289 childStatuses
.add(new Status(IStatus
.ERROR
, pluginId
, infoItem
));
292 if(throwable
== null) {
293 throwable
= getDefaultThrowable();
296 // add main execption
297 for (StackTraceElement ste
: throwable
.getStackTrace()) {
298 childStatuses
.add(new Status(IStatus
.ERROR
, pluginId
, "at " + ste
.toString()));
302 if(throwable
.getCause() != null) {
303 childStatuses
.add(new Status(IStatus
.ERROR
, pluginId
, ""));
304 childStatuses
.add(new Status(IStatus
.ERROR
, pluginId
, "Caused by : " + throwable
.getCause().toString()));
305 for (StackTraceElement ste
: throwable
.getCause().getStackTrace()) {
306 // build & add status
307 childStatuses
.add(new Status(IStatus
.ERROR
, pluginId
, "at " + ste
.toString()));
311 String finalMessage
= message
;
313 if(finalMessage
== null || finalMessage
.isEmpty()) {
314 finalMessage
= DEFAULT_MESSAGE
;
318 // add edit support contact info to message
319 finalMessage
+= MessagingUtils
.CONTACT_MESSAGE
;
322 MultiStatus ms
= new MultiStatus(pluginId
,
324 childStatuses
.toArray(new Status
[] {}),
325 throwable
.toString(),
328 errorDialog(title
, source
, throwable
, contextInfo
, finalMessage
, ms
);
332 * Displays a dialog for an exception occurring in an operation.
334 * This will be either a {@link eu.etaxonomy.taxeditor.model.CdmErrorDialog} in case of a
335 * security runtime exception or a warning {@link org.eclipse.jface.dialogs.MessageDialog} in
336 * case of any other exception.
339 * a {@link java.lang.String} object.
341 * a {@link java.lang.Object} object.
343 * a {@link org.eclipse.core.runtime.IStatus} object.
345 public static void operationDialog(final Object source
,
347 final String pluginId
,
348 final String operationlabel
,
351 Display
.getDefault().asyncExec(new Runnable() {
355 MultiStatus info
= null;
358 // FIXME cannot access TaxonomicEditorPlugin.PLUGIN_ID from here
359 // String PID = TaxonomicEditorPlugin.PLUGIN_ID;
360 String PID
= "eu.etaxonomy.taxeditor.application";
362 // checking security exceptions for every operation
363 RuntimeException securityRuntimeException
= SecurityExceptionUtils
.findSecurityRuntimeException(ex
);
365 // in case of a security exception it is a warning, else it is an error
366 if(securityRuntimeException
!= null){
367 title
= "Your changes could not be saved!";
368 warningDialog(title
, source
, String
.format("You are missing sufficient permissions for the operation \"%s\". %s", operationlabel
, hint
));
370 title
= "Error executing operation";
371 errorDialog(title
, source
, String
.format("An error occured while executing %s. %s", operationlabel
, hint
), pluginId
, ex
, true);
384 * Displays a question {@link org.eclipse.jface.dialogs.MessageDialog}.
387 * a {@link java.lang.String} object.
389 * a {@link java.lang.String} object.
392 public static boolean confirmDialog(String title
, String message
) {
393 return MessageDialog
.openQuestion(AbstractUtility
.getShell(), title
, message
);
397 * Displays a message {@link org.eclipse.jface.dialogs.MessageDialog}.
403 public static void messageDialog(final String title
, final Object source
, final String message
) {
404 MessagingUtils
.messageDialog(title
, source
, message
, null, true);
410 * Displays an error {@link org.eclipse.jface.dialogs.MessageDialog}.
415 * The object where the warning was generated (used by log4j)
417 * An informative String to be presented to the user
421 * a Throwable if one exists or null
423 public static void messageDialog(final String title
,
425 final String message
,
427 MessagingUtils
.messageDialog(title
, source
, message
, t
, true);
431 * Displays an error {@link org.eclipse.jface.dialogs.MessageDialog}.
436 * The object where the warning was generated (used by log4j)
438 * An informative String to be presented to the user
442 * a Throwable if one exists or null
444 public static void messageDialog(final String title
,
446 final String message
,
450 Display
.getDefault().asyncExec(new Runnable() {
454 MessageDialog
.openError(AbstractUtility
.getShell(), title
, message
+ getCauseRecursively(t
));
455 Class
<?
extends Object
> clazz
= source
!= null ? source
456 .getClass() : this.getClass();
457 error(clazz
, message
, t
);
463 MessageDialog
.openError(AbstractUtility
.getShell(), title
, message
+ getCauseRecursively(t
));
464 Class
<?
extends Object
> clazz
= source
!= null ? source
.getClass() : TaxeditorStorePlugin
.class;
465 error(clazz
, message
, t
);
469 public static String
getCauseRecursively(Throwable t
) {
474 if(t
.getCause() != null){
475 return getCauseRecursively(t
.getCause());
477 return String
.format("\n\nException: %s\nMessage: %s", t
.getClass().getSimpleName(), t
.getMessage());
482 * Displays a warning {@link org.eclipse.jface.dialogs.MessageDialog}.
488 public static void warningDialog(String title
, Object source
,
490 MessagingUtils
.warningDialog(title
, source
, status
.getMessage());
494 * Standard warning dialog for the case when the application is not yet connected to the datasource
498 public static void noDataSourceWarningDialog(Object source
) {
501 "Application is not connected to a datastore",
503 "The requested operation is only available when "
504 + "connected to a datasource. You may choose a datasource to connect to or create a new one in the datasource view.");
508 * Displays a warning {@link org.eclipse.jface.dialogs.MessageDialog}.
513 * The object where the warning was generated (used by log4j)
515 * An informative String to be presented to the user
517 public static void warningDialog(final String title
, final Object source
, final String message
) {
518 Display
.getDefault().asyncExec(new Runnable() {
522 MessageDialog
.openWarning(AbstractUtility
.getShell(), title
, message
);
523 Class
<?
extends Object
> clazz
= source
!= null ? source
524 .getClass() : AbstractUtility
.class;
525 warn(clazz
, message
);
531 * Displays an information {@link org.eclipse.jface.dialogs.MessageDialog}.
536 public static void informationDialog(final String title
, final IStatus status
) {
537 MessagingUtils
.informationDialog(title
, status
.getMessage());
541 * Displays an information {@link org.eclipse.jface.dialogs.MessageDialog}.
544 * a {@link java.lang.String} object.
546 * a {@link java.lang.String} object.
548 public static void informationDialog(final String title
,
549 final String message
) {
550 Display
.getDefault().asyncExec(new Runnable() {
554 MessageDialog
.openInformation(AbstractUtility
.getShell(), title
, message
);
560 * Open a message box that informs the user about unimplemented
561 * functionality. This method is for developer convenience.
564 * a {@link java.lang.Object} object.
566 public static void notImplementedMessage(Object source
) {
567 warningDialog("Not yet implemented", source
,
568 "This functionality is not yet implemented.");