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