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 }