001/* 002 * jDTAUS Core Utilities 003 * Copyright (C) 2005 Christian Schulte 004 * <cs@schulte.it> 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License, or any later version. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 019 * 020 */ 021package org.jdtaus.core.lang.util; 022 023import java.io.File; 024import java.net.URL; 025import org.jdtaus.core.container.ContainerFactory; 026import org.jdtaus.core.container.Implementation; 027import org.jdtaus.core.container.ModelFactory; 028import org.jdtaus.core.container.Specification; 029import org.jdtaus.core.lang.ExceptionEvent; 030import org.jdtaus.core.lang.ExceptionListener; 031import org.jdtaus.core.messages.BugReportMessage; 032import org.jdtaus.core.messages.ExceptionMessage; 033import org.jdtaus.core.messages.UndefinedApplicationStateMessage; 034import org.jdtaus.core.text.Message; 035import org.jdtaus.core.text.MessageEvent; 036import org.jdtaus.core.text.Messages; 037import org.jdtaus.core.text.spi.ApplicationLogger; 038 039/** 040 * {@code ExceptionListener} resolving exceptions to corresponding application 041 * messages. 042 * 043 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 044 * @version $JDTAUS: ExceptionMessageProducer.java 8641 2012-09-27 06:45:17Z schulte $ 045 * 046 * @see #onException(ExceptionEvent) 047 * @see org.jdtaus.core.text.util.SwingMessagePane 048 * @see org.jdtaus.core.text.util.MessageLogger 049 */ 050public final class ExceptionMessageProducer implements ExceptionListener 051{ 052 //--Constructors------------------------------------------------------------ 053 054// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausConstructors 055 // This section is managed by jdtaus-container-mojo. 056 057// </editor-fold>//GEN-END:jdtausConstructors 058 059 //------------------------------------------------------------Constructors-- 060 //--Dependencies------------------------------------------------------------ 061 062// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies 063 // This section is managed by jdtaus-container-mojo. 064 065 /** 066 * Gets the configured <code>ApplicationLogger</code> implementation. 067 * 068 * @return The configured <code>ApplicationLogger</code> implementation. 069 */ 070 private ApplicationLogger getApplicationLogger() 071 { 072 return (ApplicationLogger) ContainerFactory.getContainer(). 073 getDependency( this, "ApplicationLogger" ); 074 075 } 076 077// </editor-fold>//GEN-END:jdtausDependencies 078 079 //------------------------------------------------------------Dependencies-- 080 //--Properties-------------------------------------------------------------- 081 082// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties 083 // This section is managed by jdtaus-container-mojo. 084 085// </editor-fold>//GEN-END:jdtausProperties 086 087 //--------------------------------------------------------------Properties-- 088 //--ExceptionListener------------------------------------------------------- 089 090 /** 091 * {@inheritDoc} 092 * <p>This method resolves exceptions provided by an application's 093 * {@code ExceptionEventSource} to corresponding {@code MessageEvent}s which 094 * an application may react to by registering a listener to its 095 * {@code MessageEventSource}. Messages for checked exceptions are resolved 096 * by using any available {@code ExceptionMessageResolver} implementation 097 * stopping at the first implementation not returning {@code null}. 098 * For exceptions which are instances of {@code RuntimeException} an 099 * additional message informing the user that the application's state is 100 * undefined and that a restart is recommended is added to the produced 101 * {@code MessageEvent}. Optionally an additional message informing the user 102 * on how to report a bug is added to the produced {@code MessageEvent} if 103 * the instance got constructed using the constructor taking that 104 * information.</p> 105 * 106 * @param event the event holding the exception. 107 * 108 * @see ExceptionMessageResolver#resolve(Exception) 109 */ 110 public void onException( final ExceptionEvent event ) 111 { 112 if ( event != null ) 113 { 114 final Throwable exception = event.getException(); 115 final Throwable rootCause = event.getRootCause(); 116 final Messages messages = new Messages(); 117 118 messages.addMessage( new ExceptionMessage( exception ) ); 119 120 if ( rootCause instanceof RuntimeException ) 121 { 122 messages.addMessage( new UndefinedApplicationStateMessage() ); 123 124 if ( this.logDirectory != null ) 125 { 126 messages.addMessage( 127 new BugReportMessage( this.logDirectory, 128 this.trackerUrl, 129 this.reportAddress ) ); 130 131 } 132 } 133 else if ( rootCause instanceof Exception ) 134 { 135 final Message[] resolved = 136 this.resolveMessages( (Exception) rootCause ); 137 138 if ( resolved != null ) 139 { 140 messages.addMessages( resolved ); 141 } 142 } 143 144 this.getApplicationLogger().log( 145 new MessageEvent( this, 146 messages.getMessages(), 147 MessageEvent.ERROR ) ); 148 149 } 150 } 151 152 //-------------------------------------------------------ExceptionListener-- 153 //--ExceptionReporter------------------------------------------------------- 154 155 /** 156 * Directory holding the application's log files. 157 * @serial 158 */ 159 private File logDirectory; 160 161 /** 162 * URL of the online bugtracking system. 163 * @serial 164 */ 165 private URL trackerUrl; 166 167 /** 168 * Mail address to send the bugreport to. 169 * @serial 170 */ 171 private String reportAddress; 172 173 /** Creates a new {@code ExceptionMessageProducer} instance. */ 174 public ExceptionMessageProducer() 175 { 176 super(); 177 this.logDirectory = null; 178 this.trackerUrl = null; 179 this.reportAddress = null; 180 } 181 182 /** 183 * Creates a new {@code ExceptionMessageProducer} instance taking the 184 * application's logfile directory, an URL to the application's online 185 * bugtracking system, and an email address where to send bugreports to 186 * alternatively. 187 * 188 * @param logDirectory the directory holding the application's logfiles. 189 * @param trackerUrl an URL to the application's online bugtracking system. 190 * @param reportAddress an email address to alternatively send bugreports 191 * to. 192 * 193 * @throws NullPointerException if either {@code logDirectory}, 194 * {@code trackerUrl} or {@code reportAddress} is {@code null}. 195 */ 196 public ExceptionMessageProducer( final File logDirectory, 197 final URL trackerUrl, 198 final String reportAddress ) 199 { 200 super(); 201 if ( logDirectory == null ) 202 { 203 throw new NullPointerException( "logDirectory" ); 204 } 205 if ( trackerUrl == null ) 206 { 207 throw new NullPointerException( "trackerUrl" ); 208 } 209 if ( reportAddress == null ) 210 { 211 throw new NullPointerException( "reportAddress" ); 212 } 213 214 this.logDirectory = logDirectory; 215 this.trackerUrl = trackerUrl; 216 this.reportAddress = reportAddress; 217 } 218 219 /** 220 * Resolves application messages for a given exception by querying any 221 * available {@code ExceptionMessageResolver} implementation stopping at the 222 * first implementation not returning {@code null}. 223 * 224 * @param exception the exception to resolve application messages for. 225 * 226 * @throws NullPointerException if {@code exception} is {@code null}. 227 */ 228 private Message[] resolveMessages( final Exception exception ) 229 { 230 if ( exception == null ) 231 { 232 throw new NullPointerException( "exception" ); 233 } 234 235 Message[] messages = null; 236 final Specification spec = ModelFactory.getModel().getModules(). 237 getSpecification( ExceptionMessageResolver.class.getName() ); 238 239 final Implementation[] resolvers = spec.getImplementations(). 240 getImplementations(); 241 242 for ( int i = resolvers.length - 1; i >= 0 && messages == null; i-- ) 243 { 244 final ExceptionMessageResolver resolver = 245 (ExceptionMessageResolver) ContainerFactory.getContainer(). 246 getObject( ExceptionMessageResolver.class, 247 resolvers[i].getName() ); 248 249 messages = resolver.resolve( exception ); 250 } 251 252 return messages; 253 } 254 255 //-------------------------------------------------------ExceptionReporter-- 256}