    001    /* ========================================================================
    002     * JCommon : a free general purpose class library for the Java(tm) platform
    003     * ========================================================================
    004     *
    005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
    006     *
    007     * Project Info:  http://www.jfree.org/jcommon/index.html
    008     *
    009     * This library is free software; you can redistribute it and/or modify it
    010     * under the terms of the GNU Lesser General Public License as published by
    011     * the Free Software Foundation; either version 2.1 of the License, or
    012     * (at your option) any later version.
    013     *
    014     * This library is distributed in the hope that it will be useful, but
    015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017     * License for more details.
    018     *
    019     * You should have received a copy of the GNU Lesser General Public
    020     * License along with this library; if not, write to the Free Software
    021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022     * USA.
    023     *
    024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025     * in the United States and other countries.]
    026     *
    027     * --------
    028     * Log.java
    029     * --------
    030     * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
    031     *
    032     * Original Author:  Thomas Morgner (taquera@sherito.org);
    033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034     *
    035     * $Id: Log.java,v 1.4 2005/11/14 10:55:43 mungady Exp $
    036     *
    037     * Changes
    038     * -------
    039     * 29-Apr-2003 : Distilled from the JFreeReport project and moved into JCommon
    040     * 11-Jun-2003 : Removing LogTarget did not work.
    041     *
    042     */
    043
    044    package org.jfree.util;
    045
    046    import java.util.ArrayList;
    047    import java.util.Arrays;
    048    import java.util.HashMap;
    049
    050    /**
    051     * A simple logging facility. Create a class implementing the {@link org.jfree.util.LogTarget}
    052     * interface to use this feature.
    053     *
    054     * @author Thomas Morgner
    055     */
    056    public class Log {
    057
    058        /**
    059         * A simple message class.
    060         */
    061        public static class SimpleMessage {
    062
    063            /**
    064             * The message.
    065             */
    066            private String message;
    067
    068            /**
    069             * The parameters.
    070             */
    071            private Object[] param;
    072
    073            /**
    074             * Creates a new message.
    075             *
    076             * @param message the message text.
    077             * @param param1  parameter 1.
    078             */
    079            public SimpleMessage(final String message, final Object param1) {
    080                this.message = message;
    081                this.param = new Object[]{param1};
    082            }
    083
    084            /**
    085             * Creates a new message.
    086             *
    087             * @param message the message text.
    088             * @param param1  parameter 1.
    089             * @param param2  parameter 2.
    090             */
    091            public SimpleMessage(final String message, final Object param1,
    092                                 final Object param2) {
    093                this.message = message;
    094                this.param = new Object[]{param1, param2};
    095            }
    096
    097            /**
    098             * Creates a new message.
    099             *
    100             * @param message the message text.
    101             * @param param1  parameter 1.
    102             * @param param2  parameter 2.
    103             * @param param3  parameter 3.
    104             */
    105            public SimpleMessage(final String message, final Object param1,
    106                                 final Object param2, final Object param3) {
    107                this.message = message;
    108                this.param = new Object[]{param1, param2, param3};
    109            }
    110
    111            /**
    112             * Creates a new message.
    113             *
    114             * @param message the message text.
    115             * @param param1  parameter 1.
    116             * @param param2  parameter 2.
    117             * @param param3  parameter 3.
    118             * @param param4  parameter 4.
    119             */
    120            public SimpleMessage(final String message, final Object param1,
    121                                 final Object param2, final Object param3,
    122                                 final Object param4) {
    123                this.message = message;
    124                this.param = new Object[]{param1, param2, param3, param4};
    125            }
    126
    127            /**
    128             * Creates a new message.
    129             *
    130             * @param message the message text.
    131             * @param param   the parameters.
    132             */
    133            public SimpleMessage(final String message, final Object[] param) {
    134                this.message = message;
    135                this.param = param;
    136            }
    137
    138            /**
    139             * Returns a string representation of the message (useful for debugging).
    140             *
    141             * @return the string.
    142             */
    143            public String toString() {
    144                final StringBuffer b = new StringBuffer();
    145                b.append(this.message);
    146                if (this.param != null) {
    147                    for (int i = 0; i < this.param.length; i++) {
    148                        b.append(this.param[i]);
    149                    }
    150                }
    151                return b.toString();
    152            }
    153        }
    154
    155
    156        /**
    157         * The logging threshold.
    158         */
    159        private int debuglevel;
    160
    161        /**
    162         * Storage for the log targets.
    163         */
    164        private LogTarget[] logTargets;
    165
    166        /** The log contexts. */
    167        private HashMap logContexts;
    168
    169        /**
    170         * the singleton instance of the Log system.
    171         */
    172        private static Log singleton;
    173
    174        /**
    175         * Creates a new Log instance. The Log is used to manage the log targets.
    176         */
    177        protected Log() {
    178            this.logContexts = new HashMap();
    179            this.logTargets = new LogTarget[0];
    180            this.debuglevel = 100;
    181        }
    182
    183        /**
    184         * Returns the singleton Log instance. A new instance is created if necessary.
    185         *
    186         * @return the singleton instance.
    187         */
    188        public static synchronized Log getInstance() {
    189            if (singleton == null) {
    190                singleton = new Log();
    191            }
    192            return singleton;
    193        }
    194
    195        /**
    196         * Redefines or clears the currently used log instance.
    197         *
    198         * @param log the new log instance or null, to return to the default implementation.
    199         */
    200        protected static synchronized void defineLog(final Log log) {
    201            singleton = log;
    202        }
    203
    204        /**
    205         * Returns the currently defined debug level. The higher the level, the more details
    206         * are printed.
    207         *
    208         * @return the debug level.
    209         */
    210        public int getDebuglevel() {
    211            return this.debuglevel;
    212        }
    213
    214        /**
    215         * Defines the debug level for the log system.
    216         *
    217         * @param debuglevel the new debug level
    218         * @see #getDebuglevel()
    219         */
    220        protected void setDebuglevel(final int debuglevel) {
    221            this.debuglevel = debuglevel;
    222        }
    223
    224        /**
    225         * Adds a log target to this facility. Log targets get informed, via the LogTarget interface,
    226         * whenever a message is logged with this class.
    227         *
    228         * @param target the target.
    229         */
    230        public synchronized void addTarget(final LogTarget target) {
    231            if (target == null) {
    232                throw new NullPointerException();
    233            }
    234            final LogTarget[] data = new LogTarget[this.logTargets.length + 1];
    235            System.arraycopy(this.logTargets, 0, data, 0, this.logTargets.length);
    236            data[this.logTargets.length] = target;
    237            this.logTargets = data;
    238        }
    239
    240        /**
    241         * Removes a log target from this facility.
    242         *
    243         * @param target the target to remove.
    244         */
    245        public synchronized void removeTarget(final LogTarget target) {
    246            if (target == null) {
    247                throw new NullPointerException();
    248            }
    249            final ArrayList l = new ArrayList();
    250            l.addAll(Arrays.asList(this.logTargets));
    251            l.remove(target);
    252
    253            final LogTarget[] targets = new LogTarget[l.size()];
    254            this.logTargets = (LogTarget[]) l.toArray(targets);
    255        }
    256
    257        /**
    258         * Returns the registered logtargets.
    259         *
    260         * @return the logtargets.
    261         */
    262        public LogTarget[] getTargets() {
    263            final LogTarget[] targets = new LogTarget[this.logTargets.length];
    264            System.arraycopy(targets, 0, this.logTargets, 0, this.logTargets.length);
    265            return targets;
    266        }
    267
    268        /**
    269         * Replaces all log targets by the given target.
    270         *
    271         * @param target the new and only logtarget.
    272         */
    273        public synchronized void replaceTargets(final LogTarget target) {
    274            if (target == null) {
    275                throw new NullPointerException();
    276            }
    277            this.logTargets = new LogTarget[]{target};
    278        }
    279
    280        /**
    281         * A convenience method for logging a 'debug' message.
    282         *
    283         * @param message the message.
    284         */
    285        public static void debug(final Object message) {
    286            log(LogTarget.DEBUG, message);
    287        }
    288
    289        /**
    290         * A convenience method for logging a 'debug' message.
    291         *
    292         * @param message the message.
    293         * @param e       the exception.
    294         */
    295        public static void debug(final Object message, final Exception e) {
    296            log(LogTarget.DEBUG, message, e);
    297        }
    298
    299        /**
    300         * A convenience method for logging an 'info' message.
    301         *
    302         * @param message the message.
    303         */
    304        public static void info(final Object message) {
    305            log(LogTarget.INFO, message);
    306        }
    307
    308        /**
    309         * A convenience method for logging an 'info' message.
    310         *
    311         * @param message the message.
    312         * @param e       the exception.
    313         */
    314        public static void info(final Object message, final Exception e) {
    315            log(LogTarget.INFO, message, e);
    316        }
    317
    318        /**
    319         * A convenience method for logging a 'warning' message.
    320         *
    321         * @param message the message.
    322         */
    323        public static void warn(final Object message) {
    324            log(LogTarget.WARN, message);
    325        }
    326
    327        /**
    328         * A convenience method for logging a 'warning' message.
    329         *
    330         * @param message the message.
    331         * @param e       the exception.
    332         */
    333        public static void warn(final Object message, final Exception e) {
    334            log(LogTarget.WARN, message, e);
    335        }
    336
    337        /**
    338         * A convenience method for logging an 'error' message.
    339         *
    340         * @param message the message.
    341         */
    342        public static void error(final Object message) {
    343            log(LogTarget.ERROR, message);
    344        }
    345
    346        /**
    347         * A convenience method for logging an 'error' message.
    348         *
    349         * @param message the message.
    350         * @param e       the exception.
    351         */
    352        public static void error(final Object message, final Exception e) {
    353            log(LogTarget.ERROR, message, e);
    354        }
    355
    356        /**
    357         * Logs a message to the main log stream.  All attached log targets will also
    358         * receive this message. If the given log-level is higher than the given debug-level
    359         * in the main config file, no logging will be done.
    360         *
    361         * @param level   log level of the message.
    362         * @param message text to be logged.
    363         */
    364        protected void doLog(int level, final Object message) {
    365            if (level > 3) {
    366                level = 3;
    367            }
    368            if (level <= this.debuglevel) {
    369                for (int i = 0; i < this.logTargets.length; i++) {
    370                    final LogTarget t = this.logTargets[i];
    371                    t.log(level, message);
    372                }
    373            }
    374        }
    375
    376        /**
    377         * Logs a message to the main log stream.  All attached log targets will also
    378         * receive this message. If the given log-level is higher than the given debug-level
    379         * in the main config file, no logging will be done.
    380         *
    381         * @param level   log level of the message.
    382         * @param message text to be logged.
    383         */
    384        public static void log(final int level, final Object message) {
    385            getInstance().doLog(level, message);
    386        }
    387
    388        /**
    389         * Logs a message to the main log stream. All attached logTargets will also
    390         * receive this message. If the given log-level is higher than the given debug-level
    391         * in the main config file, no logging will be done.
    392         * <p/>
    393         * The exception's stacktrace will be appended to the log-stream
    394         *
    395         * @param level   log level of the message.
    396         * @param message text to be logged.
    397         * @param e       the exception, which should be logged.
    398         */
    399        public static void log(final int level, final Object message, final Exception e) {
    400            getInstance().doLog(level, message, e);
    401        }
    402
    403        /**
    404         * Logs a message to the main log stream. All attached logTargets will also
    405         * receive this message. If the given log-level is higher than the given debug-level
    406         * in the main config file, no logging will be done.
    407         * <p/>
    408         * The exception's stacktrace will be appended to the log-stream
    409         *
    410         * @param level   log level of the message.
    411         * @param message text to be logged.
    412         * @param e       the exception, which should be logged.
    413         */
    414        protected void doLog(int level, final Object message, final Exception e) {
    415            if (level > 3) {
    416                level = 3;
    417            }
    418
    419            if (level <= this.debuglevel) {
    420                for (int i = 0; i < this.logTargets.length; i++) {
    421                    final LogTarget t = this.logTargets[i];
    422                    t.log(level, message, e);
    423                }
    424            }
    425        }
    426
    427        /**
    428         * Initializes the logging system. Implementors should
    429         * override this method to supply their own log configuration.
    430         */
    431        public void init() {
    432            // this method is intentionally empty.
    433        }
    434
    435        /**
    436         * Returns true, if the log level allows debug messages to be
    437         * printed.
    438         *
    439         * @return true, if messages with an log level of DEBUG are allowed.
    440         */
    441        public static boolean isDebugEnabled() {
    442            return getInstance().getDebuglevel() <= LogTarget.DEBUG;
    443        }
    444
    445        /**
    446         * Returns true, if the log level allows informational
    447         * messages to be printed.
    448         *
    449         * @return true, if messages with an log level of INFO are allowed.
    450         */
    451        public static boolean isInfoEnabled() {
    452            return getInstance().getDebuglevel() <= LogTarget.INFO;
    453        }
    454
    455        /**
    456         * Returns true, if the log level allows warning messages to be
    457         * printed.
    458         *
    459         * @return true, if messages with an log level of WARN are allowed.
    460         */
    461        public static boolean isWarningEnabled() {
    462            return getInstance().getDebuglevel() <= LogTarget.WARN;
    463        }
    464
    465        /**
    466         * Returns true, if the log level allows error messages to be
    467         * printed.
    468         *
    469         * @return true, if messages with an log level of ERROR are allowed.
    470         */
    471        public static boolean isErrorEnabled() {
    472            return getInstance().getDebuglevel() <= LogTarget.ERROR;
    473        }
    474
    475        /**
    476         * Creates a log context.
    477         *
    478         * @param context  the class (<code>null</code> not permitted).
    479         *
    480         * @return A log context.
    481         */
    482        public static LogContext createContext(final Class context) {
    483            return createContext(context.getName());
    484        }
    485
    486        /**
    487         * Creates a log context.
    488         *
    489         * @param context  the label for the context.
    490         *
    491         * @return A log context.
    492         */
    493        public static LogContext createContext(final String context) {
    494            return getInstance().internalCreateContext(context);
    495        }
    496
    497        /**
    498         * Creates a log context.
    499         *
    500         * @param context  the name of the logging context (a common prefix).
    501         *
    502         * @return A log context.
    503         */
    504        protected LogContext internalCreateContext(final String context) {
    505            synchronized (this) {
    506                LogContext ctx = (LogContext) this.logContexts.get(context);
    507                if (ctx == null) {
    508                    ctx = new LogContext(context);
    509                    this.logContexts.put(context, ctx);
    510                }
    511                return ctx;
    512            }
    513        }
    514
    515    }