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 }