001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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 }