View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.wss4j.common.util;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.lang.reflect.InvocationTargetException;
25  import java.net.MalformedURLException;
26  import java.net.URL;
27  import java.nio.file.Files;
28  import java.nio.file.Paths;
29  import java.security.AccessController;
30  import java.security.PrivilegedAction;
31  
32  import org.apache.wss4j.common.ext.WSSecurityException;
33  
34  /**
35   * Load resources (or images) from various sources.
36   * <p/>
37   */
38  public final class Loader {
39      private static final org.slf4j.Logger LOG =
40              org.slf4j.LoggerFactory.getLogger(Loader.class);
41  
42      private Loader() {
43          // complete
44      }
45  
46      public static InputStream loadInputStream(ClassLoader loader, String resource)
47          throws WSSecurityException, IOException {
48          InputStream is = null;
49          if (resource != null) {
50              URL url = null;
51              // First see if it's a URL
52              try {
53                  url = new URL(resource);
54              } catch (MalformedURLException ex) { //NOPMD
55                  // skip
56              }
57              // If not a URL, then try to load the resource
58              if (url == null) {
59                  url = Loader.getResource(loader, resource);
60              }
61              if (url != null) {
62                  is = url.openStream();
63              }
64  
65              //
66              // If we don't find it, then look on the file system.
67              //
68              if (is == null) {
69                  try {
70                      is = Files.newInputStream(Paths.get(resource));
71                  } catch (Exception e) {
72                      LOG.debug(e.getMessage(), e);
73                      throw new WSSecurityException(
74                          WSSecurityException.ErrorCode.FAILURE, e, "resourceNotFound", new Object[] {resource}
75                      );
76                  }
77              }
78          }
79          return is;
80      }
81  
82      /**
83       * This method will search for <code>resource</code> in different
84       * places. The search order is as follows:
85       * <ol>
86       * <p><li>Search for <code>resource</code> using the thread context
87       * class loader under Java2.
88       * <p><li>Try one last time with
89       * <code>ClassLoader.getSystemResource(resource)</code>, that is is
90       * using the system class loader in JDK 1.2 and virtual machine's
91       * built-in class loader in JDK 1.1.
92       * </ol>
93       * <p/>
94       *
95       * @param resource
96       * @return the url to the resource or null if not found
97       */
98      public static URL getResource(String resource) {
99          URL url = null;
100         try {
101             ClassLoader classLoader = getTCL();
102             if (classLoader != null) {
103                 if (LOG.isDebugEnabled()) {
104                     LOG.debug("Trying to find [" + resource + "] using " + classLoader + " class loader.");
105                 }
106                 url = classLoader.getResource(resource);
107                 if (url == null && resource.startsWith("/")) {
108                     //certain classloaders need it without the leading /
109                     url = classLoader.getResource(resource.substring(1));
110                 }
111                 if (url != null) {
112                     return url;
113                 }
114             }
115         } catch (Exception e) {
116             LOG.warn("Caught Exception while in Loader.getResource. This may be innocuous.", e);
117         }
118 
119         ClassLoader cluClassloader = Loader.class.getClassLoader();
120         if (cluClassloader == null) {
121             cluClassloader = ClassLoader.getSystemClassLoader();
122         }
123         url = cluClassloader.getResource(resource);
124         if (url == null && resource.startsWith("/")) {
125             //certain classloaders need it without the leading /
126             url = cluClassloader.getResource(resource.substring(1));
127         }
128         if (url != null) {
129             return url;
130         }
131 
132         // Last ditch attempt: get the resource from the class path. It
133         // may be the case that clazz was loaded by the Extension class
134         // loader which the parent of the system class loader. Hence the
135         // code below.
136         LOG.debug("Trying to find [{}] using ClassLoader.getSystemResource().", resource);
137         return ClassLoader.getSystemResource(resource);
138     }
139 
140 
141     /**
142      * This method will search for <code>resource</code> in different
143      * places. The search order is as follows:
144      * <ol>
145      * <p><li>Search for <code>resource</code> using the supplied class loader.
146      * If that fails, search for <code>resource</code> using the thread context
147      * class loader.
148      * <p><li>Try one last time with
149      * <code>ClassLoader.getSystemResource(resource)</code>, that is is
150      * using the system class loader in JDK 1.2 and virtual machine's
151      * built-in class loader in JDK 1.1.
152      * </ol>
153      * <p/>
154      *
155      * @param resource
156      * @return the url to the resource or null if not found
157      */
158     public static URL getResource(ClassLoader loader, String resource) {
159         URL url = null;
160         try {
161             if (loader != null) {
162                 if (LOG.isDebugEnabled()) {
163                     LOG.debug("Trying to find [" + resource + "] using " + loader + " class loader.");
164                 }
165                 url = loader.getResource(resource);
166                 if (url == null && resource.startsWith("/")) {
167                     //certain classloaders need it without the leading /
168                     url = loader.getResource(resource.substring(1));
169                 }
170                 if (url != null) {
171                     return url;
172                 }
173             }
174         } catch (Exception e) {
175             LOG.warn("Caught Exception while in Loader.getResource. This may be innocuous.", e);
176         }
177         return getResource(resource);
178     }
179 
180     /**
181      * This is a convenience method to load a resource as a stream. <p/> The
182      * algorithm used to find the resource is given in getResource()
183      *
184      * @param resourceName The name of the resource to load
185      */
186     public static InputStream getResourceAsStream(String resourceName) {
187         URL url = getResource(resourceName);
188 
189         try {
190             return (url != null) ? url.openStream() : null;
191         } catch (IOException e) {
192             LOG.debug(e.getMessage(), e);
193             return null;
194         }
195     }
196 
197     /**
198      * Get the Thread context class loader.
199      * <p/>
200      *
201      * @return the Thread context class loader
202      * @throws IllegalAccessException
203      * @throws InvocationTargetException
204      */
205     public static ClassLoader getTCL() throws IllegalAccessException, InvocationTargetException {
206         return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
207             public ClassLoader run() {
208                 return Thread.currentThread().getContextClassLoader();
209             }
210         });
211     }
212 
213     /**
214      * Get the class loader of the class argument
215      * <p/>
216      *
217      * @return the class loader of the argument
218      */
219     public static ClassLoader getClassLoader(final Class<?> clazz) {
220         return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
221             public ClassLoader run() {
222                 return clazz.getClassLoader();
223             }
224         });
225     }
226 
227     /**
228      * Try the specified classloader and then fall back to the loadClass
229      * <p/>
230      *
231      * @param loader
232      * @param clazz
233      * @return Class
234      * @throws ClassNotFoundException
235      */
236     public static Class<?> loadClass(ClassLoader loader, String clazz) throws ClassNotFoundException {
237         try {
238             if (loader != null) {
239                 Class<?> c = loader.loadClass(clazz);
240                 if (c != null) {
241                     return c;
242                 }
243             }
244         } catch (Exception e) {
245             LOG.warn(e.getMessage(), e);
246         }
247         return loadClass(clazz, true);
248     }
249 
250     /**
251      * Try the specified classloader and then fall back to the loadClass
252      * <p/>
253      *
254      * @param loader
255      * @param clazz
256      * @param type
257      * @return Class
258      * @throws ClassNotFoundException
259      */
260     public static <T> Class<? extends T> loadClass(ClassLoader loader,
261                                                    String clazz,
262                                                    Class<T> type) throws ClassNotFoundException {
263         try {
264             if (loader != null) {
265                 Class<?> c = loader.loadClass(clazz);
266                 if (c != null) {
267                     return c.asSubclass(type);
268                 }
269             }
270         } catch (Exception e) {
271             LOG.warn(e.getMessage(), e);
272         }
273         return loadClass(clazz, true, type);
274     }
275 
276     /**
277      * If running under JDK 1.2 load the specified class using the
278      * <code>Thread</code> <code>contextClassLoader</code> if that
279      * fails try Class.forname.
280      * <p/>
281      *
282      * @param clazz
283      * @return the class
284      * @throws ClassNotFoundException
285      */
286     public static Class<?> loadClass(String clazz) throws ClassNotFoundException {
287         return loadClass(clazz, true);
288     }
289 
290     /**
291      * If running under JDK 1.2 load the specified class using the
292      * <code>Thread</code> <code>contextClassLoader</code> if that
293      * fails try Class.forname.
294      * <p/>
295      *
296      * @param clazz
297      * @param type  Type to cast it to
298      * @return the class
299      * @throws ClassNotFoundException
300      */
301     public static <T> Class<? extends T> loadClass(String clazz, Class<T> type)
302             throws ClassNotFoundException {
303         return loadClass(clazz, true, type);
304     }
305 
306     public static <T> Class<? extends T> loadClass(String clazz,
307                                                    boolean warn,
308                                                    Class<T> type) throws ClassNotFoundException {
309         return loadClass(clazz, warn).asSubclass(type);
310     }
311 
312     public static Class<?> loadClass(String clazz, boolean warn) throws ClassNotFoundException {
313         try {
314             ClassLoader tcl = getTCL();
315 
316             if (tcl != null) {
317                 Class<?> c = tcl.loadClass(clazz);
318                 if (c != null) {
319                     return c;
320                 }
321             }
322         } catch (Exception e) {
323             if (warn) {
324                 LOG.warn(e.getMessage(), e);
325             } else {
326                 LOG.debug(e.getMessage(), e);
327             }
328         }
329 
330         return loadClass2(clazz, null);
331     }
332 
333     private static Class<?> loadClass2(String className, Class<?> callingClass)
334         throws ClassNotFoundException {
335         try {
336             return Class.forName(className);
337         } catch (ClassNotFoundException ex) {
338             try {
339                 if (Loader.class.getClassLoader() != null) {
340                     return Loader.class.getClassLoader().loadClass(className);
341                 }
342             } catch (ClassNotFoundException exc) {
343                 if (callingClass != null && callingClass.getClassLoader() != null) {
344                     return callingClass.getClassLoader().loadClass(className);
345                 }
346             }
347             throw ex;
348         }
349     }
350 }