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  package org.apache.log4j.helpers;
    19
    20  import java.net.URL;
    21  import java.lang.reflect.Method;
    22  import java.lang.reflect.InvocationTargetException;
    23  import java.io.InterruptedIOException;
    24
    25
    26  /**
    27     Load resources (or images) from various sources.
    28
    29    @author Ceki G&uuml;lc&uuml;
    30   */
    31
    32  public class Loader  {
    33
    34    static final String TSTR = "Caught Exception while in Loader.getResource. This may be innocuous.";
    35
    36    // We conservatively assume that we are running under Java 1.x
    37    static private boolean java1 = true;
    38
    39    static private boolean ignoreTCL = false;
    40
    41    static {
    42      String prop = OptionConverter.getSystemProperty("java.version", null);
    43
    44      if(prop != null) {
    45        int i = prop.indexOf('.');
    46        if(i != -1) {
    47  	if(prop.charAt(i+1) != '1')
    48  	  java1 = false;
    49        }
    50      }
    51      String ignoreTCLProp = OptionConverter.getSystemProperty("log4j.ignoreTCL", null);
    52      if(ignoreTCLProp != null) {
    53        ignoreTCL = OptionConverter.toBoolean(ignoreTCLProp, true);
    54      }
    55    }
    56
    57    /**
    58     *  Get a resource by delegating to getResource(String).
    59     *  @param resource resource name
    60     *  @param clazz class, ignored.
    61     *  @return URL to resource or null.
    62     *  @deprecated as of 1.2.
    63     */
    64    public static URL getResource(String resource, Class clazz) {
    65        return getResource(resource);
    66    }
    67
    68    /**
    69       This method will search for <code>resource</code> in different
    70       places. The search order is as follows:
    71
    72       <ol>
    73
    74       <p><li>Search for <code>resource</code> using the thread context
    75       class loader under Java2. If that fails, search for
    76       <code>resource</code> using the class loader that loaded this
    77       class (<code>Loader</code>). Under JDK 1.1, only the the class
    78       loader that loaded this class (<code>Loader</code>) is used.
    79
    80       <p><li>Try one last time with
    81       <code>ClassLoader.getSystemResource(resource)</code>, that is is
    82       using the system class loader in JDK 1.2 and virtual machine's
    83       built-in class loader in JDK 1.1.
    84
    85       </ol>
    86    */
    87    static public URL getResource(String resource) {
    88      ClassLoader classLoader = null;
    89      URL url = null;
    90
    91      try {
    92    	if(!java1 && !ignoreTCL) {
    93    	  classLoader = getTCL();
    94    	  if(classLoader != null) {
    95    	    LogLog.debug("Trying to find ["+resource+"] using context classloader "
    96    			 +classLoader+".");
    97    	    url = classLoader.getResource(resource);
    98    	    if(url != null) {
    99    	      return url;
    100   	    }
    101   	  }
    102   	}
    103
    104   	// We could not find resource. Ler us now try with the
    105   	// classloader that loaded this class.
    106   	classLoader = Loader.class.getClassLoader();
    107   	if(classLoader != null) {
    108   	  LogLog.debug("Trying to find ["+resource+"] using "+classLoader
    109   		       +" class loader.");
    110   	  url = classLoader.getResource(resource);
    111   	  if(url != null) {
    112   	    return url;
    113   	  }
    114   	}
    115     } catch(IllegalAccessException t) {
    116         LogLog.warn(TSTR, t);
    117     } catch(InvocationTargetException t) {
    118         if (t.getTargetException() instanceof InterruptedException
    119                 || t.getTargetException() instanceof InterruptedIOException) {
    120             Thread.currentThread().interrupt();
    121         }
    122         LogLog.warn(TSTR, t);
    123     } catch(Throwable t) {
    124       //
    125       //  can't be InterruptedException or InterruptedIOException
    126       //    since not declared, must be error or RuntimeError.
    127       LogLog.warn(TSTR, t);
    128     }
    129
    130     // Last ditch attempt: get the resource from the class path. It
    131     // may be the case that clazz was loaded by the Extentsion class
    132     // loader which the parent of the system class loader. Hence the
    133     // code below.
    134     LogLog.debug("Trying to find ["+resource+
    135   		   "] using ClassLoader.getSystemResource().");
    136     return ClassLoader.getSystemResource(resource);
    137   }
    138
    139   /**
    140      Are we running under JDK 1.x?
    141   */
    142   public
    143   static
    144   boolean isJava1() {
    145     return java1;
    146   }
    147
    148   /**
    149     * Get the Thread Context Loader which is a JDK 1.2 feature. If we
    150     * are running under JDK 1.1 or anything else goes wrong the method
    151     * returns <code>null<code>.
    152     *
    153     *  */
    154   private static ClassLoader getTCL() throws IllegalAccessException,
    155     InvocationTargetException {
    156
    157     // Are we running on a JDK 1.2 or later system?
    158     Method method = null;
    159     try {
    160       method = Thread.class.getMethod("getContextClassLoader", null);
    161     } catch (NoSuchMethodException e) {
    162       // We are running on JDK 1.1
    163       return null;
    164     }
    165
    166     return (ClassLoader) method.invoke(Thread.currentThread(), null);
    167   }
    168
    169
    170
    171   /**
    172    * If running under JDK 1.2 load the specified class using the
    173    *  <code>Thread</code> <code>contextClassLoader</code> if that
    174    *  fails try Class.forname. Under JDK 1.1 only Class.forName is
    175    *  used.
    176    *
    177    */
    178   static public Class loadClass (String clazz) throws ClassNotFoundException {
    179     // Just call Class.forName(clazz) if we are running under JDK 1.1
    180     // or if we are instructed to ignore the TCL.
    181     if(java1 || ignoreTCL) {
    182       return Class.forName(clazz);
    183     } else {
    184       try {
    185 	    return getTCL().loadClass(clazz);
    186       }
    187       // we reached here because tcl was null or because of a
    188       // security exception, or because clazz could not be loaded...
    189       // In any case we now try one more time
    190       catch(InvocationTargetException e) {
    191           if (e.getTargetException() instanceof InterruptedException
    192                   || e.getTargetException() instanceof InterruptedIOException) {
    193               Thread.currentThread().interrupt();
    194           }
    195       } catch(Throwable t) {
    196       }
    197     }
    198     return Class.forName(clazz);
    199   }
    200 }