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    }