View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18
    19  package org.apache.commons.logging.impl;
    20
    21  import java.io.InputStream;
    22  import java.io.Serializable;
    23  import java.lang.reflect.InvocationTargetException;
    24  import java.lang.reflect.Method;
    25  import java.security.AccessController;
    26  import java.security.PrivilegedAction;
    27  import java.text.DateFormat;
    28  import java.text.SimpleDateFormat;
    29  import java.util.Date;
    30  import java.util.Properties;
    31
    32  import org.apache.commons.logging.Log;
    33  import org.apache.commons.logging.LogConfigurationException;
    34
    35  /**
    36   * <p>Simple implementation of Log that sends all enabled log messages,
    37   * for all defined loggers, to System.err.  The following system properties
    38   * are supported to configure the behavior of this logger:</p>
    39   * <ul>
    40   * <li><code>org.apache.commons.logging.simplelog.defaultlog</code> -
    41   *     Default logging detail level for all instances of SimpleLog.
    42   *     Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
    43   *     If not specified, defaults to "info". </li>
    44   * <li><code>org.apache.commons.logging.simplelog.log.xxxxx</code> -
    45   *     Logging detail level for a SimpleLog instance named "xxxxx".
    46   *     Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
    47   *     If not specified, the default logging detail level is used.</li>
    48   * <li><code>org.apache.commons.logging.simplelog.showlogname</code> -
    49   *     Set to <code>true</code> if you want the Log instance name to be
    50   *     included in output messages. Defaults to <code>false</code>.</li>
    51   * <li><code>org.apache.commons.logging.simplelog.showShortLogname</code> -
    52   *     Set to <code>true</code> if you want the last component of the name to be
    53   *     included in output messages. Defaults to <code>true</code>.</li>
    54   * <li><code>org.apache.commons.logging.simplelog.showdatetime</code> -
    55   *     Set to <code>true</code> if you want the current date and time
    56   *     to be included in output messages. Default is <code>false</code>.</li>
    57   * <li><code>org.apache.commons.logging.simplelog.dateTimeFormat</code> -
    58   *     The date and time format to be used in the output messages.
    59   *     The pattern describing the date and time format is the same that is
    60   *     used in <code>java.text.SimpleDateFormat</code>. If the format is not
    61   *     specified or is invalid, the default format is used.
    62   *     The default format is <code>yyyy/MM/dd HH:mm:ss:SSS zzz</code>.</li>
    63   * </ul>
    64   *
    65   * <p>In addition to looking for system properties with the names specified
    66   * above, this implementation also checks for a class loader resource named
    67   * <code>"simplelog.properties"</code>, and includes any matching definitions
    68   * from this resource (if it exists).</p>
    69   *
    70   * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
    71   * @author Rod Waldhoff
    72   * @author Robert Burrell Donkin
    73   *
    74   * @version $Id: SimpleLog.java 581090 2007-10-01 22:01:06Z dennisl $
    75   */
    76  public class SimpleLog implements Log, Serializable {
    77
    78
    79      // ------------------------------------------------------- Class Attributes
    80
    81      /** All system properties used by <code>SimpleLog</code> start with this */
    82      static protected final String systemPrefix =
    83          "org.apache.commons.logging.simplelog.";
    84
    85      /** Properties loaded from simplelog.properties */
    86      static protected final Properties simpleLogProps = new Properties();
    87
    88      /** The default format to use when formating dates */
    89      static protected final String DEFAULT_DATE_TIME_FORMAT =
    90          "yyyy/MM/dd HH:mm:ss:SSS zzz";
    91
    92      /** Include the instance name in the log message? */
    93      static protected boolean showLogName = false;
    94      /** Include the short name ( last component ) of the logger in the log
    95       *  message. Defaults to true - otherwise we'll be lost in a flood of
    96       *  messages without knowing who sends them.
    97       */
    98      static protected boolean showShortName = true;
    99      /** Include the current time in the log message */
    100     static protected boolean showDateTime = false;
    101     /** The date and time format to use in the log message */
    102     static protected String dateTimeFormat = DEFAULT_DATE_TIME_FORMAT;
    103
    104     /**
    105      * Used to format times.
    106      * <p>
    107      * Any code that accesses this object should first obtain a lock on it,
    108      * ie use synchronized(dateFormatter); this requirement was introduced
    109      * in 1.1.1 to fix an existing thread safety bug (SimpleDateFormat.format
    110      * is not thread-safe).
    111      */
    112     static protected DateFormat dateFormatter = null;
    113
    114     // ---------------------------------------------------- Log Level Constants
    115
    116
    117     /** "Trace" level logging. */
    118     public static final int LOG_LEVEL_TRACE  = 1;
    119     /** "Debug" level logging. */
    120     public static final int LOG_LEVEL_DEBUG  = 2;
    121     /** "Info" level logging. */
    122     public static final int LOG_LEVEL_INFO   = 3;
    123     /** "Warn" level logging. */
    124     public static final int LOG_LEVEL_WARN   = 4;
    125     /** "Error" level logging. */
    126     public static final int LOG_LEVEL_ERROR  = 5;
    127     /** "Fatal" level logging. */
    128     public static final int LOG_LEVEL_FATAL  = 6;
    129
    130     /** Enable all logging levels */
    131     public static final int LOG_LEVEL_ALL    = (LOG_LEVEL_TRACE - 1);
    132
    133     /** Enable no logging levels */
    134     public static final int LOG_LEVEL_OFF    = (LOG_LEVEL_FATAL + 1);
    135
    136     // ------------------------------------------------------------ Initializer
    137
    138     private static String getStringProperty(String name) {
    139         String prop = null;
    140         try {
    141             prop = System.getProperty(name);
    142         } catch (SecurityException e) {
    143             ; // Ignore
    144         }
    145         return (prop == null) ? simpleLogProps.getProperty(name) : prop;
    146     }
    147
    148     private static String getStringProperty(String name, String dephault) {
    149         String prop = getStringProperty(name);
    150         return (prop == null) ? dephault : prop;
    151     }
    152
    153     private static boolean getBooleanProperty(String name, boolean dephault) {
    154         String prop = getStringProperty(name);
    155         return (prop == null) ? dephault : "true".equalsIgnoreCase(prop);
    156     }
    157
    158     // Initialize class attributes.
    159     // Load properties file, if found.
    160     // Override with system properties.
    161     static {
    162         // Add props from the resource simplelog.properties
    163         InputStream in = getResourceAsStream("simplelog.properties");
    164         if(null != in) {
    165             try {
    166                 simpleLogProps.load(in);
    167                 in.close();
    168             } catch(java.io.IOException e) {
    169                 // ignored
    170             }
    171         }
    172
    173         showLogName = getBooleanProperty( systemPrefix + "showlogname", showLogName);
    174         showShortName = getBooleanProperty( systemPrefix + "showShortLogname", showShortName);
    175         showDateTime = getBooleanProperty( systemPrefix + "showdatetime", showDateTime);
    176
    177         if(showDateTime) {
    178             dateTimeFormat = getStringProperty(systemPrefix + "dateTimeFormat",
    179                                                dateTimeFormat);
    180             try {
    181                 dateFormatter = new SimpleDateFormat(dateTimeFormat);
    182             } catch(IllegalArgumentException e) {
    183                 // If the format pattern is invalid - use the default format
    184                 dateTimeFormat = DEFAULT_DATE_TIME_FORMAT;
    185                 dateFormatter = new SimpleDateFormat(dateTimeFormat);
    186             }
    187         }
    188     }
    189
    190     // ------------------------------------------------------------- Attributes
    191
    192     /** The name of this simple log instance */
    193     protected String logName = null;
    194     /** The current log level */
    195     protected int currentLogLevel;
    196     /** The short name of this simple log instance */
    197     private String shortLogName = null;
    198
    199
    200     // ------------------------------------------------------------ Constructor
    201
    202     /**
    203      * Construct a simple log with given name.
    204      *
    205      * @param name log name
    206      */
    207     public SimpleLog(String name) {
    208
    209         logName = name;
    210
    211         // Set initial log level
    212         // Used to be: set default log level to ERROR
    213         // IMHO it should be lower, but at least info ( costin ).
    214         setLevel(SimpleLog.LOG_LEVEL_INFO);
    215
    216         // Set log level from properties
    217         String lvl = getStringProperty(systemPrefix + "log." + logName);
    218         int i = String.valueOf(name).lastIndexOf(".");
    219         while(null == lvl && i > -1) {
    220             name = name.substring(0,i);
    221             lvl = getStringProperty(systemPrefix + "log." + name);
    222             i = String.valueOf(name).lastIndexOf(".");
    223         }
    224
    225         if(null == lvl) {
    226             lvl =  getStringProperty(systemPrefix + "defaultlog");
    227         }
    228
    229         if("all".equalsIgnoreCase(lvl)) {
    230             setLevel(SimpleLog.LOG_LEVEL_ALL);
    231         } else if("trace".equalsIgnoreCase(lvl)) {
    232             setLevel(SimpleLog.LOG_LEVEL_TRACE);
    233         } else if("debug".equalsIgnoreCase(lvl)) {
    234             setLevel(SimpleLog.LOG_LEVEL_DEBUG);
    235         } else if("info".equalsIgnoreCase(lvl)) {
    236             setLevel(SimpleLog.LOG_LEVEL_INFO);
    237         } else if("warn".equalsIgnoreCase(lvl)) {
    238             setLevel(SimpleLog.LOG_LEVEL_WARN);
    239         } else if("error".equalsIgnoreCase(lvl)) {
    240             setLevel(SimpleLog.LOG_LEVEL_ERROR);
    241         } else if("fatal".equalsIgnoreCase(lvl)) {
    242             setLevel(SimpleLog.LOG_LEVEL_FATAL);
    243         } else if("off".equalsIgnoreCase(lvl)) {
    244             setLevel(SimpleLog.LOG_LEVEL_OFF);
    245         }
    246
    247     }
    248
    249
    250     // -------------------------------------------------------- Properties
    251
    252     /**
    253      * <p> Set logging level. </p>
    254      *
    255      * @param currentLogLevel new logging level
    256      */
    257     public void setLevel(int currentLogLevel) {
    258
    259         this.currentLogLevel = currentLogLevel;
    260
    261     }
    262
    263
    264     /**
    265      * <p> Get logging level. </p>
    266      */
    267     public int getLevel() {
    268
    269         return currentLogLevel;
    270     }
    271
    272
    273     // -------------------------------------------------------- Logging Methods
    274
    275
    276     /**
    277      * <p> Do the actual logging.
    278      * This method assembles the message
    279      * and then calls <code>write()</code> to cause it to be written.</p>
    280      *
    281      * @param type One of the LOG_LEVEL_XXX constants defining the log level
    282      * @param message The message itself (typically a String)
    283      * @param t The exception whose stack trace should be logged
    284      */
    285     protected void log(int type, Object message, Throwable t) {
    286         // Use a string buffer for better performance
    287         StringBuffer buf = new StringBuffer();
    288
    289         // Append date-time if so configured
    290         if(showDateTime) {
    291             Date now = new Date();
    292             String dateText;
    293             synchronized(dateFormatter) {
    294                 dateText = dateFormatter.format(now);
    295             }
    296             buf.append(dateText);
    297             buf.append(" ");
    298         }
    299
    300         // Append a readable representation of the log level
    301         switch(type) {
    302             case SimpleLog.LOG_LEVEL_TRACE: buf.append("[TRACE] "); break;
    303             case SimpleLog.LOG_LEVEL_DEBUG: buf.append("[DEBUG] "); break;
    304             case SimpleLog.LOG_LEVEL_INFO:  buf.append("[INFO] ");  break;
    305             case SimpleLog.LOG_LEVEL_WARN:  buf.append("[WARN] ");  break;
    306             case SimpleLog.LOG_LEVEL_ERROR: buf.append("[ERROR] "); break;
    307             case SimpleLog.LOG_LEVEL_FATAL: buf.append("[FATAL] "); break;
    308         }
    309
    310         // Append the name of the log instance if so configured
    311         if( showShortName) {
    312             if( shortLogName==null ) {
    313                 // Cut all but the last component of the name for both styles
    314                 shortLogName = logName.substring(logName.lastIndexOf(".") + 1);
    315                 shortLogName =
    316                     shortLogName.substring(shortLogName.lastIndexOf("/") + 1);
    317             }
    318             buf.append(String.valueOf(shortLogName)).append(" - ");
    319         } else if(showLogName) {
    320             buf.append(String.valueOf(logName)).append(" - ");
    321         }
    322
    323         // Append the message
    324         buf.append(String.valueOf(message));
    325
    326         // Append stack trace if not null
    327         if(t != null) {
    328             buf.append(" <");
    329             buf.append(t.toString());
    330             buf.append(">");
    331
    332             java.io.StringWriter sw= new java.io.StringWriter(1024);
    333             java.io.PrintWriter pw= new java.io.PrintWriter(sw);
    334             t.printStackTrace(pw);
    335             pw.close();
    336             buf.append(sw.toString());
    337         }
    338
    339         // Print to the appropriate destination
    340         write(buf);
    341
    342     }
    343
    344
    345     /**
    346      * <p>Write the content of the message accumulated in the specified
    347      * <code>StringBuffer</code> to the appropriate output destination.  The
    348      * default implementation writes to <code>System.err</code>.</p>
    349      *
    350      * @param buffer A <code>StringBuffer</code> containing the accumulated
    351      *  text to be logged
    352      */
    353     protected void write(StringBuffer buffer) {
    354
    355         System.err.println(buffer.toString());
    356
    357     }
    358
    359
    360     /**
    361      * Is the given log level currently enabled?
    362      *
    363      * @param logLevel is this level enabled?
    364      */
    365     protected boolean isLevelEnabled(int logLevel) {
    366         // log level are numerically ordered so can use simple numeric
    367         // comparison
    368         return (logLevel >= currentLogLevel);
    369     }
    370
    371
    372     // -------------------------------------------------------- Log Implementation
    373
    374
    375     /**
    376      * Logs a message with
    377      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG</code>.
    378      *
    379      * @param message to log
    380      * @see org.apache.commons.logging.Log#debug(Object)
    381      */
    382     public final void debug(Object message) {
    383
    384         if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
    385             log(SimpleLog.LOG_LEVEL_DEBUG, message, null);
    386         }
    387     }
    388
    389
    390     /**
    391      * Logs a message with
    392      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG</code>.
    393      *
    394      * @param message to log
    395      * @param t log this cause
    396      * @see org.apache.commons.logging.Log#debug(Object, Throwable)
    397      */
    398     public final void debug(Object message, Throwable t) {
    399
    400         if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
    401             log(SimpleLog.LOG_LEVEL_DEBUG, message, t);
    402         }
    403     }
    404
    405
    406     /**
    407      * Logs a message with
    408      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE</code>.
    409      *
    410      * @param message to log
    411      * @see org.apache.commons.logging.Log#trace(Object)
    412      */
    413     public final void trace(Object message) {
    414
    415         if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) {
    416             log(SimpleLog.LOG_LEVEL_TRACE, message, null);
    417         }
    418     }
    419
    420
    421     /**
    422      * Logs a message with
    423      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE</code>.
    424      *
    425      * @param message to log
    426      * @param t log this cause
    427      * @see org.apache.commons.logging.Log#trace(Object, Throwable)
    428      */
    429     public final void trace(Object message, Throwable t) {
    430
    431         if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) {
    432             log(SimpleLog.LOG_LEVEL_TRACE, message, t);
    433         }
    434     }
    435
    436
    437     /**
    438      * Logs a message with
    439      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO</code>.
    440      *
    441      * @param message to log
    442      * @see org.apache.commons.logging.Log#info(Object)
    443      */
    444     public final void info(Object message) {
    445
    446         if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) {
    447             log(SimpleLog.LOG_LEVEL_INFO,message,null);
    448         }
    449     }
    450
    451
    452     /**
    453      * Logs a message with
    454      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO</code>.
    455      *
    456      * @param message to log
    457      * @param t log this cause
    458      * @see org.apache.commons.logging.Log#info(Object, Throwable)
    459      */
    460     public final void info(Object message, Throwable t) {
    461
    462         if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) {
    463             log(SimpleLog.LOG_LEVEL_INFO, message, t);
    464         }
    465     }
    466
    467
    468     /**
    469      * Logs a message with
    470      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN</code>.
    471      *
    472      * @param message to log
    473      * @see org.apache.commons.logging.Log#warn(Object)
    474      */
    475     public final void warn(Object message) {
    476
    477         if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) {
    478             log(SimpleLog.LOG_LEVEL_WARN, message, null);
    479         }
    480     }
    481
    482
    483     /**
    484      * Logs a message with
    485      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN</code>.
    486      *
    487      * @param message to log
    488      * @param t log this cause
    489      * @see org.apache.commons.logging.Log#warn(Object, Throwable)
    490      */
    491     public final void warn(Object message, Throwable t) {
    492
    493         if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) {
    494             log(SimpleLog.LOG_LEVEL_WARN, message, t);
    495         }
    496     }
    497
    498
    499     /**
    500      * Logs a message with
    501      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR</code>.
    502      *
    503      * @param message to log
    504      * @see org.apache.commons.logging.Log#error(Object)
    505      */
    506     public final void error(Object message) {
    507
    508         if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) {
    509             log(SimpleLog.LOG_LEVEL_ERROR, message, null);
    510         }
    511     }
    512
    513
    514     /**
    515      * Logs a message with
    516      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR</code>.
    517      *
    518      * @param message to log
    519      * @param t log this cause
    520      * @see org.apache.commons.logging.Log#error(Object, Throwable)
    521      */
    522     public final void error(Object message, Throwable t) {
    523
    524         if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) {
    525             log(SimpleLog.LOG_LEVEL_ERROR, message, t);
    526         }
    527     }
    528
    529
    530     /**
    531      * Log a message with
    532      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL</code>.
    533      *
    534      * @param message to log
    535      * @see org.apache.commons.logging.Log#fatal(Object)
    536      */
    537     public final void fatal(Object message) {
    538
    539         if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) {
    540             log(SimpleLog.LOG_LEVEL_FATAL, message, null);
    541         }
    542     }
    543
    544
    545     /**
    546      * Logs a message with
    547      * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL</code>.
    548      *
    549      * @param message to log
    550      * @param t log this cause
    551      * @see org.apache.commons.logging.Log#fatal(Object, Throwable)
    552      */
    553     public final void fatal(Object message, Throwable t) {
    554
    555         if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) {
    556             log(SimpleLog.LOG_LEVEL_FATAL, message, t);
    557         }
    558     }
    559
    560
    561     /**
    562      * <p> Are debug messages currently enabled? </p>
    563      *
    564      * <p> This allows expensive operations such as <code>String</code>
    565      * concatenation to be avoided when the message will be ignored by the
    566      * logger. </p>
    567      */
    568     public final boolean isDebugEnabled() {
    569
    570         return isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG);
    571     }
    572
    573
    574     /**
    575      * <p> Are error messages currently enabled? </p>
    576      *
    577      * <p> This allows expensive operations such as <code>String</code>
    578      * concatenation to be avoided when the message will be ignored by the
    579      * logger. </p>
    580      */
    581     public final boolean isErrorEnabled() {
    582
    583         return isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR);
    584     }
    585
    586
    587     /**
    588      * <p> Are fatal messages currently enabled? </p>
    589      *
    590      * <p> This allows expensive operations such as <code>String</code>
    591      * concatenation to be avoided when the message will be ignored by the
    592      * logger. </p>
    593      */
    594     public final boolean isFatalEnabled() {
    595
    596         return isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL);
    597     }
    598
    599
    600     /**
    601      * <p> Are info messages currently enabled? </p>
    602      *
    603      * <p> This allows expensive operations such as <code>String</code>
    604      * concatenation to be avoided when the message will be ignored by the
    605      * logger. </p>
    606      */
    607     public final boolean isInfoEnabled() {
    608
    609         return isLevelEnabled(SimpleLog.LOG_LEVEL_INFO);
    610     }
    611
    612
    613     /**
    614      * <p> Are trace messages currently enabled? </p>
    615      *
    616      * <p> This allows expensive operations such as <code>String</code>
    617      * concatenation to be avoided when the message will be ignored by the
    618      * logger. </p>
    619      */
    620     public final boolean isTraceEnabled() {
    621
    622         return isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE);
    623     }
    624
    625
    626     /**
    627      * <p> Are warn messages currently enabled? </p>
    628      *
    629      * <p> This allows expensive operations such as <code>String</code>
    630      * concatenation to be avoided when the message will be ignored by the
    631      * logger. </p>
    632      */
    633     public final boolean isWarnEnabled() {
    634
    635         return isLevelEnabled(SimpleLog.LOG_LEVEL_WARN);
    636     }
    637
    638
    639     /**
    640      * Return the thread context class loader if available.
    641      * Otherwise return null.
    642      *
    643      * The thread context class loader is available for JDK 1.2
    644      * or later, if certain security conditions are met.
    645      *
    646      * @exception LogConfigurationException if a suitable class loader
    647      * cannot be identified.
    648      */
    649     private static ClassLoader getContextClassLoader()
    650     {
    651         ClassLoader classLoader = null;
    652
    653         if (classLoader == null) {
    654             try {
    655                 // Are we running on a JDK 1.2 or later system?
    656                 Method method = Thread.class.getMethod("getContextClassLoader",
    657                         (Class[]) null);
    658
    659                 // Get the thread context class loader (if there is one)
    660                 try {
    661                     classLoader = (ClassLoader)method.invoke(Thread.currentThread(),
    662                             (Class[]) null);
    663                 } catch (IllegalAccessException e) {
    664                     ;  // ignore
    665                 } catch (InvocationTargetException e) {
    666                     /**
    667                      * InvocationTargetException is thrown by 'invoke' when
    668                      * the method being invoked (getContextClassLoader) throws
    669                      * an exception.
    670                      *
    671                      * getContextClassLoader() throws SecurityException when
    672                      * the context class loader isn't an ancestor of the
    673                      * calling class's class loader, or if security
    674                      * permissions are restricted.
    675                      *
    676                      * In the first case (not related), we want to ignore and
    677                      * keep going.  We cannot help but also ignore the second
    678                      * with the logic below, but other calls elsewhere (to
    679                      * obtain a class loader) will trigger this exception where
    680                      * we can make a distinction.
    681                      */
    682                     if (e.getTargetException() instanceof SecurityException) {
    683                         ;  // ignore
    684                     } else {
    685                         // Capture 'e.getTargetException()' exception for details
    686                         // alternate: log 'e.getTargetException()', and pass back 'e'.
    687                         throw new LogConfigurationException
    688                             ("Unexpected InvocationTargetException", e.getTargetException());
    689                     }
    690                 }
    691             } catch (NoSuchMethodException e) {
    692                 // Assume we are running on JDK 1.1
    693                 ;  // ignore
    694             }
    695         }
    696
    697         if (classLoader == null) {
    698             classLoader = SimpleLog.class.getClassLoader();
    699         }
    700
    701         // Return the selected class loader
    702         return classLoader;
    703     }
    704
    705     private static InputStream getResourceAsStream(final String name)
    706     {
    707         return (InputStream)AccessController.doPrivileged(
    708             new PrivilegedAction() {
    709                 public Object run() {
    710                     ClassLoader threadCL = getContextClassLoader();
    711
    712                     if (threadCL != null) {
    713                         return threadCL.getResourceAsStream(name);
    714                     } else {
    715                         return ClassLoader.getSystemResourceAsStream(name);
    716                     }
    717                 }
    718             });
    719     }
    720 }
    721