/** * Copyright (C) 2015 Valkyrie RCP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.valkyriercp.application.exceptionhandling; import org.jdesktop.swingx.JXFrame; import org.springframework.context.support.MessageSourceAccessor; import org.valkyriercp.application.ApplicationWindow; import org.valkyriercp.application.config.ApplicationConfig; import org.valkyriercp.util.ValkyrieRepository; import javax.swing.*; /** * Logs a throwable and shows a dialog about it to the user. * * @author Geoffrey De Smet * @since 0.3 */ public abstract class AbstractDialogExceptionHandler<SELF extends AbstractDialogExceptionHandler<SELF>> extends AbstractLoggingExceptionHandler<SELF> { private static final String DIALOG_EXCEPTION_HANDLER_KEY = "dialogExceptionHandler"; protected boolean modalDialog = true; protected ShutdownPolicy shutdownPolicy = ShutdownPolicy.ASK; public MessageSourceAccessor getMessageSourceAccessor() { return getApplicationConfig().messageSourceAccessor(); } public ApplicationConfig getApplicationConfig() { return ValkyrieRepository.getInstance().getApplicationConfig(); } /** * Where or not the shown dialog should be modal (see JDialog API). * The default is true; * * @param modalDialog */ public void setModalDialog(boolean modalDialog) { this.modalDialog = modalDialog; } public SELF usingModalDialog(boolean modalDialog) { setModalDialog(modalDialog); return self(); } /** * Wheter or not the user should be asked or obligated to shutdown the application. * The default is ASK. * * @param shutdownPolicy */ public void setShutdownPolicy(ShutdownPolicy shutdownPolicy) { this.shutdownPolicy = shutdownPolicy; } public SELF havingShutdownPolicy(ShutdownPolicy shutdownPolicy) { setShutdownPolicy(shutdownPolicy); return self(); } public void notifyUserAboutException(Thread thread, Throwable throwable) { Object[] options; switch (shutdownPolicy) { case NONE: options = new String[]{ getMessageSourceAccessor().getMessage(DIALOG_EXCEPTION_HANDLER_KEY + ".none.ok")}; break; case ASK: options = new String[]{ getMessageSourceAccessor().getMessage(DIALOG_EXCEPTION_HANDLER_KEY + ".ask.shutdown"), getMessageSourceAccessor().getMessage(DIALOG_EXCEPTION_HANDLER_KEY + ".ask.continue")}; break; case OBLIGATE: options = new String[]{ getMessageSourceAccessor().getMessage(DIALOG_EXCEPTION_HANDLER_KEY + ".obligate.shutdown")}; break; default: // Can not occur and if it does it will crash the event thread throw new IllegalStateException("Unrecognized shutdownPolicy: " + shutdownPolicy); } int result = JOptionPane.showOptionDialog( resolveParentFrame(), createExceptionContent(throwable), resolveExceptionCaption(throwable), JOptionPane.DEFAULT_OPTION, resolveMessageType(), null, options, options[0]); if ((shutdownPolicy == ShutdownPolicy.ASK && result == 0) || shutdownPolicy == ShutdownPolicy.OBLIGATE) { logger.info("Shutting down due to uncaught exception."); try { getApplicationConfig().application().close(true, 1); } finally { // In case the instance() method throws an exception and an exit didn't occur System.exit(2); } } } protected JFrame resolveParentFrame() { ApplicationWindow activeWindow = getApplicationConfig().windowManager().getActiveWindow(); if(activeWindow == null) return null; return activeWindow.getControl(); } public abstract Object createExceptionContent(Throwable throwable); public abstract String resolveExceptionCaption(Throwable throwable); private int resolveMessageType() { return JOptionPane.ERROR_MESSAGE; } }