001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/framework/log/LoggerService.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.framework.log; 037 038 // J2EE 1.3 039 import java.io.BufferedOutputStream; 040 import java.io.BufferedWriter; 041 import java.io.File; 042 import java.io.FileOutputStream; 043 import java.io.FileWriter; 044 import java.io.IOException; 045 import java.net.InetAddress; 046 import java.net.UnknownHostException; 047 import java.text.DateFormat; 048 import java.util.Date; 049 import java.util.Enumeration; 050 import java.util.Map; 051 import java.util.Properties; 052 053 import javax.mail.Session; 054 055 import org.deegree.framework.jndi.JndiUtils; 056 import org.deegree.framework.mail.EMailMessage; 057 import org.deegree.framework.mail.MailHelper; 058 import org.deegree.framework.mail.MailMessage; 059 import org.deegree.framework.util.BootLogger; 060 import org.deegree.framework.version.Version; 061 import org.deegree.framework.xml.XMLFragment; 062 063 /** 064 * The Logger is used to log messages to files. This service will use a logging service provided by the application 065 * server or a 3rd party logging service such as Apache Log4J to enable asychronous call of the method log(). The log 066 * server is configured by a set of Properties which are provided to the class init. 067 * <p> 068 * There are some global properties as well: <BR> 069 * <UL> 070 * <LI><B>log.class </B>: the logging class. 071 * <LI><B>log.active </B>: to enable or disabel the logging service 072 * <LI><B>log.mail.active </B>: to activate the email notification 073 * <LI><B>log.mail.to </B>: the mail address 074 * <LI><B>log.mail.session </B>: the mail session used to send mail 075 * </UL> 076 * <P> 077 * Messages are logged using log(). If an error occurs during creation or logging, the message will be written to the 078 * server BootLogger. 079 * 080 * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </A> 081 * 082 * @author last edited by: UID=$Author: mschneider $ 083 * 084 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 085 * 086 * @see LoggerFactory 087 * @see org.deegree.framework.util.BootLogger 088 */ 089 abstract class LoggerService implements ILogger { 090 091 /** 092 * the log channel name 093 */ 094 protected static String defaultChannelName; 095 096 private static String hostAddress; 097 098 private static String hostName; 099 100 private static String mailNotificationAddress; 101 102 private static String mailSessionName; 103 104 private static Session mailSession; 105 106 private static String mailHostName; 107 108 private static boolean sendMailIsActive; 109 110 private static DateFormat df; 111 112 public void init( Properties props ) { 113 114 df = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT ); 115 116 try { 117 118 // fetch all configuration parameters 119 LoggerService.defaultChannelName = props.getProperty( "log.channel.name" ); 120 LoggerService.mailNotificationAddress = props.getProperty( "log.mail.to" ); 121 String mailerActive = props.getProperty( "log.mail.active" ); 122 LoggerService.mailSessionName = props.getProperty( "log.mail.session" ); 123 LoggerService.mailHostName = props.getProperty( "log.mail.smtphost" ); 124 125 // set defaults if not set 126 if ( mailerActive == null || mailerActive.equalsIgnoreCase( "false" ) ) { 127 LoggerService.sendMailIsActive = false; 128 } 129 if ( defaultChannelName == null ) { 130 LoggerService.defaultChannelName = LoggerService.class.getName(); 131 } 132 if ( mailNotificationAddress == null ) { 133 LoggerService.mailNotificationAddress = "UNKNOWN@" + LoggerService.mailHostName; 134 } 135 136 hostAddress = InetAddress.getLocalHost().getHostAddress(); 137 hostName = InetAddress.getLocalHost().getHostName(); 138 139 } catch ( UnknownHostException ex ) { 140 BootLogger.log( "Unable to determine host: " + ex.getMessage() ); 141 } catch ( Exception ex ) { 142 ex.printStackTrace(); 143 BootLogger.log( "Error while initializing " + LoggerService.class.getName() + " : " + ex.getMessage() ); 144 } finally { 145 BootLogger.logDebug( "Using: defaultChannelName=" + defaultChannelName + ", mailNotificationAddress=" 146 + mailNotificationAddress + ", mailSessionName=" + mailSessionName 147 + ", log.mail.active=" + LoggerService.sendMailIsActive ); 148 } 149 } 150 151 /** 152 * Create logger instance 153 * 154 */ 155 protected LoggerService() { 156 // only callable for the package. 157 } 158 159 /** 160 * Log error with exception 161 * 162 * @param message 163 * the log message 164 * @param e 165 * the exception to be logged 166 * @param properties 167 * a given Property file in which specific email notification possibilities are saved. 168 */ 169 public final void logError( String message, Throwable e, Map<?, ?> properties ) { 170 this.logError( message, e ); 171 if ( sendMailIsActive ) { 172 this.sendMail( message, e, properties ); 173 } 174 } 175 176 /** 177 * Log warning message 178 * 179 * @param message 180 * the log message 181 */ 182 public abstract void logWarning( String message ); 183 184 /** 185 * Log warning message with exception 186 * 187 * @param message 188 * the log message 189 * @param e 190 * the exception to be logged 191 */ 192 public abstract void logWarning( String message, Throwable e ); 193 194 /** 195 * Log info message 196 * 197 * @param message 198 * the log message 199 */ 200 public abstract void logInfo( String message ); 201 202 /** 203 * Log info message 204 * 205 * @param message 206 * the log message 207 * @param e 208 * the exception to be logged 209 */ 210 public abstract void logInfo( String message, Throwable e ); 211 212 /** 213 * Log debug message 214 * 215 * @param message 216 * the log message 217 */ 218 public abstract void logDebug( String message ); 219 220 /** 221 * Log debug message. 222 * 223 * @param message 224 * the log message 225 * @param e 226 * the exception to be logged 227 */ 228 public abstract void logDebug( String message, Throwable e ); 229 230 /** 231 * Logs the given text to the specified file if log level is set to <code>LOG_DEBUG</code>. 232 * 233 * @param file 234 * file to log to 235 * @param content 236 * text to be logged 237 */ 238 public void logDebugFile( File file, String content ) { 239 if ( getLevel() == LOG_DEBUG ) { 240 logDebug( "Writing debug file '" + file.getAbsolutePath() + "'." ); 241 BufferedWriter writer = null; 242 try { 243 writer = new BufferedWriter( new FileWriter( file ) ); 244 writer.write( content ); 245 } catch ( IOException e ) { 246 String msg = "Could not write to debug file '" + file.getAbsolutePath() + "'."; 247 logError( msg, e ); 248 } finally { 249 if ( writer != null ) { 250 try { 251 writer.close(); 252 } catch ( IOException e ) { 253 String msg = "Error closing debug file '" + file.getAbsolutePath() + "'."; 254 logError( msg, e ); 255 } 256 } 257 } 258 } 259 } 260 261 /** 262 * Logs the given text to a temporary file (created from specified prefix and suffix) if log level is set to 263 * <code>LOG_DEBUG</code>. 264 * 265 * @see File#createTempFile(String, String) 266 * @param filePrefix 267 * prefix for the temp file name 268 * @param fileSuffix 269 * suffix for the temp file name, can be null (then ".tmp" is used) 270 * @param content 271 * text to be logged 272 */ 273 public void logDebugFile( String filePrefix, String fileSuffix, String content ) { 274 if ( getLevel() == LOG_DEBUG ) { 275 try { 276 File tmpFile = File.createTempFile( filePrefix, fileSuffix ); 277 logDebugFile( tmpFile, content ); 278 } catch ( IOException e ) { 279 String msg = "Cannot create debug file for prefix '" + filePrefix + "' and suffix '" + fileSuffix + "."; 280 logError( msg, e ); 281 } 282 } 283 } 284 285 /** 286 * Logs the given {@link XMLFragment} to a temporary file (created from specified prefix and suffix ".xml") if log 287 * level is set to <code>LOG_DEBUG</code>. 288 * 289 * @param filePrefix 290 * prefix for the temp file name 291 * @param fragment 292 * XMLFragment to be logged (will be pretty-printed) 293 */ 294 public void logDebugXMLFile( String filePrefix, XMLFragment fragment ) { 295 if ( getLevel() == LOG_DEBUG ) { 296 if ( fragment == null ) { 297 logDebug( "The given xmlfragment is null." ); 298 } else { 299 logDebugFile( filePrefix, ".xml", fragment.getAsPrettyString() ); 300 } 301 302 } 303 } 304 305 /** 306 * Logs the given binary data to the specified file if log level is set to <code>LOG_DEBUG</code>. 307 * 308 * @param file 309 * file to log to 310 * @param data 311 * binary data to be logged 312 */ 313 public void logDebugBinaryFile( File file, byte[] data ) { 314 if ( getLevel() == LOG_DEBUG ) { 315 logDebug( "Writing binary debug file '" + file.getAbsolutePath() + "'." ); 316 BufferedOutputStream out = null; 317 try { 318 out = new BufferedOutputStream( new FileOutputStream( file ) ); 319 out.write( data ); 320 } catch ( IOException e ) { 321 String msg = "Could not write to debug file '" + file.getAbsolutePath() + "'."; 322 logError( msg, e ); 323 } finally { 324 if ( out != null ) { 325 try { 326 out.close(); 327 } catch ( IOException e ) { 328 String msg = "Error closing debug file '" + file.getAbsolutePath() + "'."; 329 logError( msg, e ); 330 } 331 } 332 } 333 } 334 } 335 336 /** 337 * Logs the given binary data to a temporary file (created from specified prefix and suffix) if log level is set to 338 * <code>LOG_DEBUG</code>. 339 * 340 * @see File#createTempFile(String, String) 341 * @param filePrefix 342 * prefix for the temp file name 343 * @param fileSuffix 344 * suffix for the temp file name, can be null (then ".tmp" is used) 345 * @param data 346 * binary data to be logged 347 */ 348 public void logDebugBinaryFile( String filePrefix, String fileSuffix, byte[] data ) { 349 if ( getLevel() == LOG_DEBUG ) { 350 try { 351 File tmpFile = File.createTempFile( filePrefix, fileSuffix ); 352 logDebugBinaryFile( tmpFile, data ); 353 } catch ( IOException e ) { 354 String msg = "Cannot create debug file for prefix '" + filePrefix + "' and suffix '" + fileSuffix + "."; 355 logError( msg, e ); 356 } 357 } 358 } 359 360 /** 361 * Sends email with exception string. If mail session or mail notification address is null no email is send. 362 * 363 * @param message 364 * message is in mail subject 365 * @param ex 366 * full exception is displayed in body 367 * @param properties 368 * list of properties listed in body 369 */ 370 protected void sendMail( String message, Throwable ex, Map<?, ?> properties ) { 371 if ( sendMailIsActive && mailSessionName != null && mailNotificationAddress != null ) { 372 this.sendMailNotification( message, ex, properties ); 373 } 374 } 375 376 private void sendMailNotification( String message, Throwable ex, Map<?, ?> properties ) { 377 MailMessage mail; 378 StringBuffer emailBody = new StringBuffer(); 379 380 emailBody.append( "A critical error occured in " + Version.getVersion() ); 381 emailBody.append( " running on " + hostName + "/" + hostAddress ); 382 emailBody.append( " on " + df.format( new Date( System.currentTimeMillis() ) ) ); 383 emailBody.append( "\n\n" ); 384 if ( message != null ) { 385 emailBody.append( "\n\nThe error message: " + message ); 386 } 387 if ( properties != null ) { 388 emailBody.append( "\n\nRequest data:\n--------------\n" + properties.toString() ); 389 } 390 if ( ex != null ) { 391 emailBody.append( "\n\nException:\n---------\n" + ex.getMessage() ); 392 emailBody.append( "\n\nStack Trace:\n------------\n\n" + ex.toString() ); 393 } 394 emailBody.append( "\n\nSystem Info:\n--------------\n" + getSystemInfo() ); 395 396 String subject = "Critical Error:" + Version.getVersion() + " on " + hostName + "/" + hostAddress; 397 398 mail = new EMailMessage( "DO_NOT_REPLY@" + hostName, mailNotificationAddress, subject, emailBody.toString() ); 399 try { 400 if ( mailSession == null ) { 401 mailSession = this.getMailSession(); 402 } 403 new MailHelper().createAndSendMail( mail, mailSession ); 404 } catch ( Exception e ) { 405 BootLogger.logError( "Can't send email notification: " + mail.getHeader(), e ); 406 } 407 } 408 409 /** 410 * Return system information (memory and properties) as string. 411 * 412 * @return system information (memory and properties) as string. 413 */ 414 private String getSystemInfo() { 415 StringBuffer buf = new StringBuffer(); 416 buf.append( "Total Memory: " + Runtime.getRuntime().totalMemory() / 1024 + " Kilobyte\n" ); 417 buf.append( "Free Memory: " + Runtime.getRuntime().freeMemory() / 1024 + " Kilobyte\n" ); 418 java.util.Properties sysprops = System.getProperties(); 419 for ( Enumeration<Object> e = sysprops.keys(); e.hasMoreElements(); ) { 420 String key = e.nextElement().toString(); 421 String value = sysprops.getProperty( key ); 422 buf.append( key + " : " + value + "\n" ); 423 } 424 return buf.toString(); 425 } 426 427 /** 428 * 429 */ 430 private Session getMailSession() { 431 Session session = null; 432 try { 433 session = (Session) JndiUtils.lookup( mailSessionName, Session.class ); 434 } catch ( Exception ex ) { 435 BootLogger.logError( "Error while initializing " + LoggerService.class.getName() + " : " + ex.getMessage(), 436 ex ); 437 } finally { 438 if ( session == null ) { 439 Properties p = System.getProperties(); 440 p.put( "mail.smtp.host", LoggerService.mailHostName ); 441 session = Session.getDefaultInstance( p, null ); 442 } 443 } 444 return session; 445 } 446 447 }