001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028: package net.sf.jasperreports.engine.util;
029:
030: import java.net.MalformedURLException;
031: import java.net.URL;
032: import java.net.URLStreamHandler;
033: import java.net.URLStreamHandlerFactory;
034:
035: /**
036: * Provides methods for resource resolution via class loaders or URL stream handlers.
037: *
038: * @author Lucian Chirita (lucianc@users.sourceforge.net)
039: * @version $Id: JRResourcesUtil.java 1229 2006-04-19 10:27:35Z teodord $
040: */
041: public class JRResourcesUtil {
042: private static URLStreamHandlerFactory globalURLHandlerFactory;
043: private static ThreadLocalStack localURLHandlerFactoryStack = new ThreadLocalStack();
044:
045: private static ClassLoader globalClassLoader;
046: private static ThreadLocalStack localClassLoaderStack = new ThreadLocalStack();
047:
048: /**
049: * Tries to parse a <code>String</code> as an URL.
050: *
051: * @param spec the <code>String</code> to parse
052: * @param urlHandlerFactory an URL stream handler factory to use
053: * @return an URL if the parsing is successful
054: * @see #getURLHandler(String, URLStreamHandlerFactory)
055: * @see #getURLHandlerFactory(URLStreamHandlerFactory)
056: */
057: public static URL createURL(String spec,
058: URLStreamHandlerFactory urlHandlerFactory) {
059: URLStreamHandler handler = getURLHandler(spec,
060: urlHandlerFactory);
061: URL url;
062: try {
063: if (handler == null) {
064: url = new URL(spec);
065: } else {
066: url = new URL(null, spec, handler);
067: }
068: } catch (MalformedURLException e) {
069: url = null;
070: }
071: return url;
072: }
073:
074: /**
075: * Returns an URL stream handler for an URL specified as a <code>String</code>.
076: *
077: * @param spec the <code>String</code> to parse as an URL
078: * @param urlHandlerFactory an URL stream handler factory
079: * @return an URL stream handler if one was found for the protocol of the URL
080: * @see #getURLHandlerFactory(URLStreamHandlerFactory)
081: */
082: public static URLStreamHandler getURLHandler(String spec,
083: URLStreamHandlerFactory urlHandlerFactory) {
084: urlHandlerFactory = getURLHandlerFactory(urlHandlerFactory);
085:
086: URLStreamHandler handler = null;
087: if (urlHandlerFactory != null) {
088: String protocol = getURLProtocol(spec);
089: if (protocol != null) {
090: handler = urlHandlerFactory
091: .createURLStreamHandler(protocol);
092: }
093: }
094: return handler;
095: }
096:
097: private static String getURLProtocol(String spec) {
098: String protocol = null;
099:
100: spec = spec.trim();
101: int colon = spec.indexOf(':');
102: if (colon > 0) {
103: String proto = spec.substring(0, colon);
104: if (protocolValid(proto)) {
105: protocol = proto;
106: }
107: }
108:
109: return protocol;
110: }
111:
112: private static boolean protocolValid(String protocol) {
113: int length = protocol.length();
114: if (length < 1) {
115: return false;
116: }
117:
118: if (!Character.isLetter(protocol.charAt(0))) {
119: return false;
120: }
121:
122: for (int i = 1; i < length; ++i) {
123: char c = protocol.charAt(i);
124: if (!(Character.isLetterOrDigit(c) || c == '+' || c == '-' || c == '.')) {
125: return false;
126: }
127: }
128:
129: return true;
130: }
131:
132: /**
133: * Returns an URL steam handler factory.
134: * <p/>
135: * The first not null value from the following is returned:
136: * <ul>
137: * <li>the value of the parameter</li>
138: * <li>the thread local URL stream handler factory</li>
139: * <li>the global URL stream handler factory</li>
140: * </ul>
141: *
142: * @param urlHandlerFactory an URL steam handler factory that will be returned if not null
143: * @return an URL steam handler factory
144: * @see #setGlobalURLHandlerFactory(URLStreamHandlerFactory)
145: * @see #setThreadURLHandlerFactory(URLStreamHandlerFactory)
146: */
147: public static URLStreamHandlerFactory getURLHandlerFactory(
148: URLStreamHandlerFactory urlHandlerFactory) {
149: if (urlHandlerFactory == null) {
150: urlHandlerFactory = getThreadURLStreamHandlerFactory();
151: if (urlHandlerFactory == null) {
152: urlHandlerFactory = globalURLHandlerFactory;
153: }
154: }
155: return urlHandlerFactory;
156: }
157:
158: /**
159: * Returns the global URL stream handler factory.
160: *
161: * @return the global URL stream handler factory
162: * @see #setGlobalURLHandlerFactory(URLStreamHandlerFactory)
163: */
164: public static URLStreamHandlerFactory getGlobalURLStreamHandlerFactory() {
165: return globalURLHandlerFactory;
166: }
167:
168: /**
169: * Returns the thread local URL stream handler factory.
170: *
171: * @return the thread local URL stream handler factory.
172: * @see #setThreadURLHandlerFactory(URLStreamHandlerFactory)
173: */
174: public static URLStreamHandlerFactory getThreadURLStreamHandlerFactory() {
175: return (URLStreamHandlerFactory) localURLHandlerFactoryStack
176: .top();
177: }
178:
179: /**
180: * Sets the thread local URL stream handler factory.
181: *
182: * @param urlHandlerFactory an URL stream handler factory.
183: * @see #getURLHandlerFactory(URLStreamHandlerFactory)
184: * @see #resetThreadURLHandlerFactory()
185: */
186: public static void setThreadURLHandlerFactory(
187: URLStreamHandlerFactory urlHandlerFactory) {
188: localURLHandlerFactoryStack.push(urlHandlerFactory);
189: }
190:
191: /**
192: * Resets the the thread local URL stream handler factory to its previous value.
193: */
194: public static void resetThreadURLHandlerFactory() {
195: localURLHandlerFactoryStack.pop();
196: }
197:
198: /**
199: * Sets a global URL stream handler facotry to be used for resource resolution.
200: *
201: * @param urlHandlerFactory the URL stream handler factory
202: * @see #getURLHandlerFactory(URLStreamHandlerFactory)
203: */
204: public static void setGlobalURLHandlerFactory(
205: URLStreamHandlerFactory urlHandlerFactory) {
206: globalURLHandlerFactory = urlHandlerFactory;
207: }
208:
209: /**
210: * Returns a class loader.
211: * <p/>
212: * The first not null value from the following is returned:
213: * <ul>
214: * <li>the value of the parameter</li>
215: * <li>the thread local class loader</li>
216: * <li>the global class loader</li>
217: * </ul>
218: *
219: * @param classLoader a class loader that will be returned if not null
220: * @return a class loader.
221: * @see #setGlobalClassLoader(ClassLoader)
222: * @see #setThreadClassLoader(ClassLoader)
223: */
224: public static ClassLoader getClassLoader(ClassLoader classLoader) {
225: if (classLoader == null) {
226: classLoader = getThreadClassLoader();
227: if (classLoader == null) {
228: classLoader = globalClassLoader;
229: }
230: }
231: return classLoader;
232: }
233:
234: /**
235: * Returns the global class loader.
236: *
237: * @return the global class loader.
238: * @see #setGlobalClassLoader(ClassLoader)
239: */
240: public static ClassLoader getGlobalClassLoader() {
241: return globalClassLoader;
242: }
243:
244: /**
245: * Returns the thread local class loader.
246: *
247: * @return the thread local class loader.
248: * @see #setThreadClassLoader(ClassLoader)
249: */
250: public static ClassLoader getThreadClassLoader() {
251: return (ClassLoader) localClassLoaderStack.top();
252: }
253:
254: /**
255: * Sets the thread local class loader.
256: *
257: * @param classLoader a class loader
258: * @see #getClassLoader(ClassLoader)
259: * @see #resetThreadURLHandlerFactory()
260: */
261: public static void setThreadClassLoader(ClassLoader classLoader) {
262: localClassLoaderStack.push(classLoader);
263: }
264:
265: /**
266: * Resets the the thread local class loader to its previous value.
267: */
268: public static void resetClassLoader() {
269: localClassLoaderStack.pop();
270: }
271:
272: /**
273: * Sets a global class loader to be used for resource resolution.
274: *
275: * @param classLoader the class loader
276: * @see #getClassLoader(ClassLoader)
277: */
278: public static void setGlobalClassLoader(ClassLoader classLoader) {
279: globalClassLoader = classLoader;
280: }
281:
282: /**
283: * Attempts to find a resource using a class loader.
284: * <p/>
285: * The following sources are tried:
286: * <ul>
287: * <li>the class loader returned by {@link #getClassLoader(ClassLoader) <code>getClassLoader(classLoader)</code>}</li>
288: * <li>the context class loader</li>
289: * <li><code>clazz.getClassLoader()</code></li>
290: * <li><code>clazz.getResource()</code></li>
291: * </ul>
292: *
293: * @param location the resource name
294: * @param classLoader a class loader
295: * @param clazz a class
296: * @return the resource URL if found
297: */
298: public static URL findClassLoaderResource(String location,
299: ClassLoader classLoader, Class clazz) {
300: classLoader = getClassLoader(classLoader);
301:
302: URL url = null;
303:
304: if (classLoader != null) {
305: url = classLoader.getResource(location);
306: }
307:
308: if (url == null) {
309: classLoader = Thread.currentThread()
310: .getContextClassLoader();
311:
312: if (classLoader != null) {
313: url = classLoader.getResource(location);
314: }
315:
316: if (url == null) {
317: classLoader = clazz.getClassLoader();
318: if (classLoader == null) {
319: url = clazz.getResource("/" + location);
320: } else {
321: url = classLoader.getResource(location);
322: }
323: }
324: }
325:
326: return url;
327: }
328: }
|