1 /******************************************************************************* 2 * Copyright (c) 2005, 2009 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.core.runtime; 15 16 import org.eclipse.core.internal.runtime.*; 17 import org.eclipse.osgi.util.NLS; 18 19 /** 20 * Runs the given ISafeRunnable in a protected mode: exceptions and certain 21 * errors thrown in the runnable are logged and passed to the runnable's 22 * exception handler. Such exceptions are not rethrown by this method. 23 * <p> 24 * This class can be used without OSGi running. 25 * </p> 26 * @since org.eclipse.equinox.common 3.2 27 */ 28 public final class SafeRunner { 29 30 /** 31 * Runs the given runnable in a protected mode. Exceptions 32 * thrown in the runnable are logged and passed to the runnable's 33 * exception handler. Such exceptions are not rethrown by this method. 34 * <p> 35 * In addition to catching all {@link Exception} types, this method also catches certain {@link Error} 36 * types that typically result from programming errors in the code being executed. 37 * Severe errors that are not generally safe to catch are not caught by this method. 38 * </p> 39 * 40 * @param code the runnable to run 41 */ run(ISafeRunnable code)42 public static void run(ISafeRunnable code) { 43 Assert.isNotNull(code); 44 try { 45 code.run(); 46 } catch (Exception | LinkageError | AssertionError e) { 47 handleException(code, e); 48 } 49 } 50 51 /** 52 * Runs the given runnable in a protected mode and returns the result given by the runnable. Exceptions 53 * thrown in the runnable are logged and passed to the runnable's 54 * exception handler. Such exceptions are not rethrown by this method, instead null is returned. 55 * <p> 56 * In addition to catching all {@link Exception} types, this method also catches certain {@link Error} 57 * types that typically result from programming errors in the code being executed. 58 * Severe errors that are not generally safe to catch are not caught by this method. 59 * </p> 60 * @param <T> the result type 61 * 62 * @param code the runnable to run 63 * @return the result 64 * 65 * @since 3.11 66 */ run(ISafeRunnableWithResult<T> code)67 public static <T> T run(ISafeRunnableWithResult<T> code) { 68 Assert.isNotNull(code); 69 try { 70 return code.runWithResult(); 71 } catch (Exception | LinkageError | AssertionError e) { 72 handleException(code, e); 73 return null; 74 } 75 } 76 handleException(ISafeRunnable code, Throwable exception)77 private static void handleException(ISafeRunnable code, Throwable exception) { 78 if (!(exception instanceof OperationCanceledException)) { 79 String pluginId = getBundleIdOfSafeRunnable(code); 80 IStatus status = convertToStatus(exception, pluginId); 81 makeSureUserSeesException(exception, status); 82 } 83 code.handleException(exception); 84 } 85 makeSureUserSeesException(Throwable exception, IStatus status)86 private static void makeSureUserSeesException(Throwable exception, IStatus status) { 87 if (RuntimeLog.isEmpty()) { 88 exception.printStackTrace(); 89 } else { 90 RuntimeLog.log(status); 91 } 92 } 93 getBundleIdOfSafeRunnable(ISafeRunnable code)94 private static String getBundleIdOfSafeRunnable(ISafeRunnable code) { 95 Activator activator = Activator.getDefault(); 96 String pluginId = null; 97 if (activator != null) 98 pluginId = activator.getBundleId(code); 99 if (pluginId == null) 100 return IRuntimeConstants.PI_COMMON; 101 return pluginId; 102 } 103 convertToStatus(Throwable exception, String pluginId)104 private static IStatus convertToStatus(Throwable exception, String pluginId) { 105 String message = NLS.bind(CommonMessages.meta_pluginProblems, pluginId); 106 if (exception instanceof CoreException) { 107 MultiStatus status = new MultiStatus(pluginId, IRuntimeConstants.PLUGIN_ERROR, message, exception); 108 status.merge(((CoreException) exception).getStatus()); 109 return status; 110 } 111 return new Status(IStatus.ERROR, pluginId, IRuntimeConstants.PLUGIN_ERROR, message, exception); 112 } 113 }