All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.swt.internal.ExceptionStash Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * 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