![JAR search and dependency download from the Maven repository](/logo.png)
org.eclipse.swt.internal.ExceptionStash Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2021, 2023 Syntevo and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Syntevo - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.internal;
import org.eclipse.swt.widgets.Display;
/**
* The intent of this class is to insulate SWT from exceptions occurring in
* user's listeners, so that SWT remains stable and does not accidentally
* crash JVM or enter some very broken state. The supposed use is:
*
* void someSwtInternalFunction() {
* // Make a stash to collect all exceptions from user listeners
* try (ExceptionStash exceptions = new ExceptionStash ()) {
* // Perform some action that may call a throwing user's listener
* try {
* sendEvent(SWT.SomeEvent);
* } catch (Error | RuntimeException ex) {
* exceptions.stash (ex);
* }
*
* // Do some important SWT stuff that you would normally do in
* // 'finally' clause. With 'ExceptionStash' you can interleave
* // important things with listeners without making code ugly.
* MakeSureThingsDontBreak();
*
* // Perform another action that may call a throwing user's listener.
* // Done in an independent 'try' block to make sure that all events
* // are sent regardless of exceptions in some of the listeners.
* try {
* askWidgetToSendMoreEvents();
* } catch (Error | RuntimeException ex) {
* exceptions.stash (ex);
* }
*
* // Exiting from 'try' statement will close ExceptionStash and
* // re-throw collected exception. If there are multiple exceptions,
* // all subsequent ones will be added as 'Throwable.addSuppressed()'.
* }
* }
*/
public class ExceptionStash implements AutoCloseable {
Throwable storedThrowable;
public void stash(Throwable throwable) {
/* First, try to pass it to the global handler */
try {
Display display = Display.getCurrent ();
if (display != null) {
if (throwable instanceof RuntimeException runtimeEx) {
display.getRuntimeExceptionHandler().accept(runtimeEx);
/* If handler doesn't throw then the exception is fully handled */
return;
} else if (throwable instanceof Error er) {
display.getErrorHandler().accept(er);
/* If handler doesn't throw then the exception is fully handled */
return;
}
}
} catch (Throwable ex) {
/* Handler may have thrown something new */
throwable = ex;
}
/* No handler or it also thrown */
if (storedThrowable != null) {
storedThrowable.addSuppressed(throwable);
} else {
storedThrowable = throwable;
}
}
public void close() {
if (storedThrowable == null) return;
Throwable throwable = storedThrowable;
storedThrowable = null;
if (throwable instanceof RuntimeException runtimeEx) {
throw runtimeEx;
} else if (throwable instanceof Error er) {
throw er;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy