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 8795 2012-12-03 16:53:46Z 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( new BugReportMessage( 127 this.logDirectory, this.trackerUrl, 128 this.reportAddress ) ); 129 130 } 131 } 132 else if ( rootCause instanceof Exception ) 133 { 134 final Message[] resolved = 135 this.resolveMessages( (Exception) rootCause ); 136 137 if ( resolved != null ) 138 { 139 messages.addMessages( resolved ); 140 } 141 } 142 143 this.getApplicationLogger().log( 144 new MessageEvent( this, 145 messages.getMessages(), 146 MessageEvent.ERROR ) ); 147 148 } 149 } 150 151 //-------------------------------------------------------ExceptionListener-- 152 //--ExceptionMessageProducer------------------------------------------------ 153 154 /** 155 * Directory holding the application's log files. 156 * @serial 157 */ 158 private File logDirectory; 159 160 /** 161 * URL of the online bugtracking system. 162 * @serial 163 */ 164 private URL trackerUrl; 165 166 /** 167 * Mail address to send the bugreport to. 168 * @serial 169 */ 170 private String reportAddress; 171 172 /** Creates a new {@code ExceptionMessageProducer} instance. */ 173 public ExceptionMessageProducer() 174 { 175 super(); 176 this.logDirectory = null; 177 this.trackerUrl = null; 178 this.reportAddress = null; 179 } 180 181 /** 182 * Creates a new {@code ExceptionMessageProducer} instance taking the 183 * application's logfile directory. 184 * 185 * @param logDirectory The directory holding the application's logfiles. 186 * 187 * @throws NullPointerException if {@code logDirectory} is {@code null}. 188 * 189 * @since 1.14 190 */ 191 public ExceptionMessageProducer( final File logDirectory ) 192 { 193 super(); 194 if ( logDirectory == null ) 195 { 196 throw new NullPointerException( "logDirectory" ); 197 } 198 199 this.logDirectory = logDirectory; 200 this.trackerUrl = null; 201 this.reportAddress = null; 202 } 203 204 /** 205 * Creates a new {@code ExceptionMessageProducer} instance taking the 206 * application's logfile directory and an URL to the application's online 207 * bugtracking system. 208 * 209 * @param logDirectory The directory holding the application's logfiles. 210 * @param trackerUrl An URL to the application's online bugtracking system. 211 * 212 * @throws NullPointerException if either {@code logDirectory} or 213 * {@code trackerUrl} is {@code null}. 214 * 215 * @since 1.14 216 */ 217 public ExceptionMessageProducer( final File logDirectory, 218 final URL trackerUrl ) 219 { 220 super(); 221 if ( logDirectory == null ) 222 { 223 throw new NullPointerException( "logDirectory" ); 224 } 225 if ( trackerUrl == null ) 226 { 227 throw new NullPointerException( "trackerUrl" ); 228 } 229 230 this.logDirectory = logDirectory; 231 this.trackerUrl = trackerUrl; 232 this.reportAddress = null; 233 } 234 235 /** 236 * Creates a new {@code ExceptionMessageProducer} instance taking the 237 * application's logfile directory and an email address where to send 238 * bugreports to. 239 * 240 * @param logDirectory The directory holding the application's logfiles. 241 * @param reportAddress An email address to alternatively send bugreports 242 * to. 243 * 244 * @throws NullPointerException if either {@code logDirectory} or 245 * {@code reportAddress} is {@code null}. 246 * 247 * @since 1.14 248 */ 249 public ExceptionMessageProducer( final File logDirectory, 250 final String reportAddress ) 251 { 252 super(); 253 if ( logDirectory == null ) 254 { 255 throw new NullPointerException( "logDirectory" ); 256 } 257 if ( reportAddress == null ) 258 { 259 throw new NullPointerException( "reportAddress" ); 260 } 261 262 this.logDirectory = logDirectory; 263 this.trackerUrl = null; 264 this.reportAddress = reportAddress; 265 } 266 267 /** 268 * Creates a new {@code ExceptionMessageProducer} instance taking the 269 * application's logfile directory, an URL to the application's online 270 * bugtracking system, and an email address where to send bugreports to 271 * alternatively. 272 * 273 * @param logDirectory The directory holding the application's logfiles. 274 * @param trackerUrl An URL to the application's online bugtracking system. 275 * @param reportAddress An email address to alternatively send bugreports 276 * to. 277 * 278 * @throws NullPointerException if either {@code logDirectory}, 279 * {@code trackerUrl} or {@code reportAddress} is {@code null}. 280 */ 281 public ExceptionMessageProducer( final File logDirectory, 282 final URL trackerUrl, 283 final String reportAddress ) 284 { 285 super(); 286 if ( logDirectory == null ) 287 { 288 throw new NullPointerException( "logDirectory" ); 289 } 290 if ( trackerUrl == null ) 291 { 292 throw new NullPointerException( "trackerUrl" ); 293 } 294 if ( reportAddress == null ) 295 { 296 throw new NullPointerException( "reportAddress" ); 297 } 298 299 this.logDirectory = logDirectory; 300 this.trackerUrl = trackerUrl; 301 this.reportAddress = reportAddress; 302 } 303 304 /** 305 * Resolves application messages for a given exception by querying any 306 * available {@code ExceptionMessageResolver} implementation stopping at the 307 * first implementation not returning {@code null}. 308 * 309 * @param exception The exception to resolve application messages for. 310 * 311 * @throws NullPointerException if {@code exception} is {@code null}. 312 */ 313 private Message[] resolveMessages( final Exception exception ) 314 { 315 if ( exception == null ) 316 { 317 throw new NullPointerException( "exception" ); 318 } 319 320 Message[] messages = null; 321 final Specification spec = ModelFactory.getModel().getModules(). 322 getSpecification( ExceptionMessageResolver.class.getName() ); 323 324 final Implementation[] resolvers = spec.getImplementations(). 325 getImplementations(); 326 327 for ( int i = resolvers.length - 1; i >= 0 && messages == null; i-- ) 328 { 329 final ExceptionMessageResolver resolver = 330 (ExceptionMessageResolver) ContainerFactory.getContainer(). 331 getObject( ExceptionMessageResolver.class, 332 resolvers[i].getName() ); 333 334 messages = resolver.resolve( exception ); 335 } 336 337 return messages; 338 } 339 340 //------------------------------------------------ExceptionMessageProducer-- 341}