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