001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/framework/log/LoggerService.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstr. 19 030 53115 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 043 ---------------------------------------------------------------------------*/ 044 package org.deegree.framework.log; 045 046 // J2EE 1.3 047 import java.io.BufferedOutputStream; 048 import java.io.BufferedWriter; 049 import java.io.File; 050 import java.io.FileOutputStream; 051 import java.io.FileWriter; 052 import java.io.IOException; 053 import java.net.InetAddress; 054 import java.net.UnknownHostException; 055 import java.text.DateFormat; 056 import java.util.Date; 057 import java.util.Enumeration; 058 import java.util.Map; 059 import java.util.Properties; 060 061 import javax.mail.Session; 062 063 import org.deegree.framework.jndi.JndiUtils; 064 import org.deegree.framework.mail.EMailMessage; 065 import org.deegree.framework.mail.MailHelper; 066 import org.deegree.framework.mail.MailMessage; 067 import org.deegree.framework.util.BootLogger; 068 import org.deegree.framework.version.Version; 069 import org.deegree.framework.xml.XMLFragment; 070 071 /** 072 * The Logger is used to log messages to files. This service will use a logging service provided by the application 073 * server or a 3rd party logging service such as Apache Log4J to enable asychronous call of the method log(). The log 074 * server is configured by a set of Properties which are provided to the class init. 075 * <p> 076 * There are some global properties as well: <BR> 077 * <UL> 078 * <LI><B>log.class </B>: the logging class. 079 * <LI><B>log.active </B>: to enable or disabel the logging service 080 * <LI><B>log.mail.active </B>: to activate the email notification 081 * <LI><B>log.mail.to </B>: the mail address 082 * <LI><B>log.mail.session </B>: the mail session used to send mail 083 * </UL> 084 * <P> 085 * Messages are logged using log(). If an error occurs during creation or logging, the message will be written to the 086 * server BootLogger. 087 * 088 * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </A> 089 * 090 * @author last edited by: UID=$Author: apoth $ 091 * 092 * @version $Revision: 9349 $, $Date: 2007-12-27 18:12:34 +0100 (Do, 27 Dez 2007) $ 093 * 094 * @see LoggerFactory 095 * @see org.deegree.framework.util.BootLogger 096 */ 097 abstract class LoggerService implements ILogger { 098 099 protected static String defaultChannelName; 100 101 private static String hostAddress; 102 103 private static String hostName; 104 105 private static String mailNotificationAddress; 106 107 private static String mailSessionName; 108 109 private static Session mailSession; 110 111 private static String mailHostName; 112 113 private static boolean sendMailIsActive; 114 115 private static DateFormat df; 116 117 public void init( Properties props ) { 118 119 df = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT ); 120 121 try { 122 123 // fetch all configuration parameters 124 LoggerService.defaultChannelName = props.getProperty( "log.channel.name" ); 125 LoggerService.mailNotificationAddress = props.getProperty( "log.mail.to" ); 126 String mailerActive = props.getProperty( "log.mail.active" ); 127 LoggerService.mailSessionName = props.getProperty( "log.mail.session" ); 128 LoggerService.mailHostName = props.getProperty( "log.mail.smtphost" ); 129 130 // set defaults if not set 131 if ( mailerActive == null || mailerActive.equalsIgnoreCase( "false" ) ) { 132 LoggerService.sendMailIsActive = false; 133 } 134 if ( defaultChannelName == null ) { 135 LoggerService.defaultChannelName = LoggerService.class.getName(); 136 } 137 if ( mailNotificationAddress == null ) { 138 LoggerService.mailNotificationAddress = "UNKNOWN@" + LoggerService.mailHostName; 139 } 140 141 hostAddress = InetAddress.getLocalHost().getHostAddress(); 142 hostName = InetAddress.getLocalHost().getHostName(); 143 144 } catch ( UnknownHostException ex ) { 145 BootLogger.log( "Unable to determine host: " + ex.getMessage() ); 146 } catch ( Exception ex ) { 147 ex.printStackTrace(); 148 BootLogger.log( "Error while initializing " + LoggerService.class.getName() + " : " + ex.getMessage() ); 149 } finally { 150 BootLogger.logDebug( "Using: defaultChannelName=" + defaultChannelName + ", mailNotificationAddress=" 151 + mailNotificationAddress + ", mailSessionName=" + mailSessionName + ", log.mail.active=" 152 + LoggerService.sendMailIsActive ); 153 } 154 } 155 156 /** 157 * Create logger instance 158 * 159 */ 160 protected LoggerService() { 161 // only callable for the package. 162 } 163 164 /** 165 * Log error with exception 166 * 167 * @param message 168 * the log message 169 * @param e 170 * the exception to be logged 171 * @param properties 172 * a given Property file in which specific email notification possibilities are saved. 173 */ 174 public final void logError( String message, Throwable e, Map properties ) { 175 this.logError( message, e ); 176 if ( sendMailIsActive ) { 177 this.sendMail( message, e, properties ); 178 } 179 } 180 181 /** 182 * Log warning message 183 * 184 * @param message 185 * the log message 186 */ 187 public abstract void logWarning( String message ); 188 189 /** 190 * Log warning message with exception 191 * 192 * @param message 193 * the log message 194 * @param e 195 * the exception to be logged 196 */ 197 public abstract void logWarning( String message, Throwable e ); 198 199 /** 200 * Log info message 201 * 202 * @param message 203 * the log message 204 */ 205 public abstract void logInfo( String message ); 206 207 /** 208 * Log info message 209 * 210 * @param message 211 * the log message 212 * @param e 213 * the exception to be logged 214 */ 215 public abstract void logInfo( String message, Throwable e ); 216 217 /** 218 * Log debug message 219 * 220 * @param message 221 * the log message 222 */ 223 public abstract void logDebug( String message ); 224 225 /** 226 * Log debug message. 227 * 228 * @param message 229 * the log message 230 * @param e 231 * the exception to be logged 232 */ 233 public abstract void logDebug( String message, Throwable e ); 234 235 /** 236 * Logs the given text to the specified file if log level is set to <code>LOG_DEBUG</code>. 237 * 238 * @param file 239 * file to log to 240 * @param content 241 * text to be logged 242 */ 243 public void logDebugFile( File file, String content ) { 244 if ( getLevel() == LOG_DEBUG ) { 245 logDebug( "Writing debug file '" + file.getAbsolutePath() + "'." ); 246 BufferedWriter writer = null; 247 try { 248 writer = new BufferedWriter( new FileWriter( file ) ); 249 writer.write( content ); 250 } catch ( IOException e ) { 251 String msg = "Could not write to debug file '" + file.getAbsolutePath() + "'."; 252 logError( msg, e ); 253 } finally { 254 if ( writer != null ) { 255 try { 256 writer.close(); 257 } catch ( IOException e ) { 258 String msg = "Error closing debug file '" + file.getAbsolutePath() + "'."; 259 logError( msg, e ); 260 } 261 } 262 } 263 } 264 } 265 266 /** 267 * Logs the given text to a temporary file (created from specified prefix and suffix) if log level is set to 268 * <code>LOG_DEBUG</code>. 269 * 270 * @see File#createTempFile(String, String) 271 * @param filePrefix 272 * prefix for the temp file name 273 * @param fileSuffix 274 * suffix for the temp file name, can be null (then ".tmp" is used) 275 * @param content 276 * text to be logged 277 */ 278 public void logDebugFile( String filePrefix, String fileSuffix, String content ) { 279 if ( getLevel() == LOG_DEBUG ) { 280 try { 281 File tmpFile = File.createTempFile( filePrefix, fileSuffix ); 282 logDebugFile( tmpFile, content ); 283 } catch ( IOException e ) { 284 String msg = "Cannot create debug file for prefix '" + filePrefix + "' and suffix '" + fileSuffix + "."; 285 logError( msg, e ); 286 } 287 } 288 } 289 290 /** 291 * Logs the given {@link XMLFragment} to a temporary file (created from specified prefix and suffix ".xml") if log 292 * level is set to <code>LOG_DEBUG</code>. 293 * 294 * @param filePrefix 295 * prefix for the temp file name 296 * @param fragment 297 * XMLFragment to be logged (will be pretty-printed) 298 */ 299 public void logDebugXMLFile( String filePrefix, XMLFragment fragment ) { 300 if ( getLevel() == LOG_DEBUG ) { 301 logDebugFile( filePrefix, ".xml", fragment.getAsPrettyString() ); 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 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 }