001 package org.springframework.richclient.exceptionhandling; 002 003 import org.springframework.beans.factory.InitializingBean; 004 import org.springframework.context.support.MessageSourceAccessor; 005 import org.springframework.richclient.application.Application; 006 import org.springframework.richclient.application.ApplicationServicesLocator; 007 import org.springframework.richclient.application.ApplicationWindow; 008 009 import javax.swing.*; 010 011 /** 012 * Logs a throwable and shows a dialog about it to the user. 013 * @author Geoffrey De Smet 014 * @since 0.3 015 */ 016 public abstract class AbstractDialogExceptionHandler extends AbstractLoggingExceptionHandler 017 implements InitializingBean { 018 019 private static final String DIALOG_EXCEPTION_HANDLER_KEY = "dialogExceptionHandler"; 020 021 protected MessageSourceAccessor messageSourceAccessor; 022 023 protected boolean modalDialog = true; 024 protected ShutdownPolicy shutdownPolicy = ShutdownPolicy.ASK; 025 026 public void setMessageSourceAccessor(MessageSourceAccessor messageSourceAccessor) { 027 this.messageSourceAccessor = messageSourceAccessor; 028 } 029 030 /** 031 * Where or not the shown dialog should be modal (see JDialog API). 032 * The default is true; 033 * @param modalDialog 034 */ 035 public void setModalDialog(boolean modalDialog) { 036 this.modalDialog = modalDialog; 037 } 038 039 /** 040 * Wheter or not the user should be asked or obligated to shutdown the application. 041 * The default is ASK. 042 * @param shutdownPolicy 043 */ 044 public void setShutdownPolicy(ShutdownPolicy shutdownPolicy) { 045 this.shutdownPolicy = shutdownPolicy; 046 } 047 048 public void afterPropertiesSet() { 049 if (messageSourceAccessor == null) { 050 messageSourceAccessor = (MessageSourceAccessor) 051 ApplicationServicesLocator.services().getService(MessageSourceAccessor.class); 052 } 053 } 054 055 056 public void notifyUserAboutException(Thread thread, Throwable throwable) { 057 Object[] options; 058 // TODO implement ability to deal with mnemonics (for example "&Shutdown" in messages.properties) 059 switch (shutdownPolicy) { 060 case NONE: 061 options = new String[]{ 062 messageSourceAccessor.getMessage(DIALOG_EXCEPTION_HANDLER_KEY + ".none.ok")}; 063 break; 064 case ASK: 065 options = new String[]{ 066 messageSourceAccessor.getMessage(DIALOG_EXCEPTION_HANDLER_KEY + ".ask.shutdown"), 067 messageSourceAccessor.getMessage(DIALOG_EXCEPTION_HANDLER_KEY + ".ask.continue")}; 068 break; 069 case OBLIGATE: 070 options = new String[]{ 071 messageSourceAccessor.getMessage(DIALOG_EXCEPTION_HANDLER_KEY + ".obligate.shutdown")}; 072 break; 073 default: 074 // Can not occur and if it does it will crash the event thread 075 throw new IllegalStateException("Unrecognized shutdownPolicy: " + shutdownPolicy); 076 } 077 int result = JOptionPane.showOptionDialog( 078 resolveParentFrame(), 079 createExceptionContent(throwable), 080 resolveExceptionCaption(throwable), 081 JOptionPane.DEFAULT_OPTION, 082 resolveMessageType(), null, 083 options, options[0]); 084 if ((shutdownPolicy == ShutdownPolicy.ASK && result == 0) 085 || shutdownPolicy == ShutdownPolicy.OBLIGATE) { 086 logger.info("Shutting down due to uncaught exception."); 087 try { 088 if (Application.isLoaded()) { 089 Application.instance().close(true, 1); 090 } 091 } finally { 092 // In case the instance() method throws an exception and an exit didn't occur 093 System.exit(2); 094 } 095 } 096 } 097 098 protected JFrame resolveParentFrame() { 099 ApplicationWindow activeWindow = Application.isLoaded() ? Application.instance().getActiveWindow() : null; 100 return (activeWindow == null) ? null : activeWindow.getControl(); 101 } 102 103 public abstract Object createExceptionContent(Throwable throwable); 104 105 public abstract String resolveExceptionCaption(Throwable throwable); 106 107 private int resolveMessageType() { 108 switch (logLevel) { 109 case TRACE: 110 case DEBUG: 111 case INFO: 112 return JOptionPane.INFORMATION_MESSAGE; 113 case WARN: 114 return JOptionPane.WARNING_MESSAGE; 115 case ERROR: 116 case FATAL: 117 default: 118 return JOptionPane.ERROR_MESSAGE; 119 } 120 } 121 122 }