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ülcü
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 }