net.sf.jasperreports.engine.util.JRResourcesUtil Maven / Gradle / Ivy
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2009 Jaspersoft Corporation. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
package net.sf.jasperreports.engine.util;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Provides methods for resource resolution via class loaders or URL stream handlers.
*
* @author Lucian Chirita ([email protected])
* @version $Id: JRResourcesUtil.java 3717 2010-04-09 10:01:33Z teodord $
*/
public final class JRResourcesUtil
{
private static FileResolver globalFileResolver;
private static ThreadLocalStack localFileResolverStack = new ThreadLocalStack();
private static URLStreamHandlerFactory globalURLHandlerFactory;
private static ThreadLocalStack localURLHandlerFactoryStack = new ThreadLocalStack();
private static ClassLoader globalClassLoader;
private static ThreadLocalStack localClassLoaderStack = new ThreadLocalStack();
/**
* Tries to parse a String
as an URL.
*
* @param spec the String
to parse
* @param urlHandlerFactory an URL stream handler factory to use
* @return an URL if the parsing is successful
* @see #getURLHandler(String, URLStreamHandlerFactory)
* @see #getURLHandlerFactory(URLStreamHandlerFactory)
*/
public static URL createURL(String spec, URLStreamHandlerFactory urlHandlerFactory)
{
URLStreamHandler handler = getURLHandler(spec, urlHandlerFactory);
URL url;
try
{
if (handler == null)
{
url = new URL(spec);
}
else
{
url = new URL(null, spec, handler);
}
}
catch (MalformedURLException e)
{
url = null;
}
return url;
}
/**
* Returns an URL stream handler for an URL specified as a String
.
*
* @param spec the String
to parse as an URL
* @param urlHandlerFact an URL stream handler factory
* @return an URL stream handler if one was found for the protocol of the URL
* @see #getURLHandlerFactory(URLStreamHandlerFactory)
*/
public static URLStreamHandler getURLHandler(String spec, URLStreamHandlerFactory urlHandlerFact)
{
URLStreamHandlerFactory urlHandlerFactory = getURLHandlerFactory(urlHandlerFact);
URLStreamHandler handler = null;
if (urlHandlerFactory != null)
{
String protocol = getURLProtocol(spec);
if (protocol != null)
{
handler = urlHandlerFactory.createURLStreamHandler(protocol);
}
}
return handler;
}
private static String getURLProtocol(String urlSpec)
{
String protocol = null;
String spec = urlSpec.trim();
int colon = spec.indexOf(':');
if (colon > 0)
{
String proto = spec.substring(0, colon);
if (protocolValid(proto))
{
protocol = proto;
}
}
return protocol;
}
private static boolean protocolValid(String protocol)
{
int length = protocol.length();
if (length < 1)
{
return false;
}
if (!Character.isLetter(protocol.charAt(0)))
{
return false;
}
for (int i = 1; i < length; ++i)
{
char c = protocol.charAt(i);
if (!(Character.isLetterOrDigit(c) || c == '+' || c == '-' || c == '.'))
{
return false;
}
}
return true;
}
/**
* Returns a file resolver.
*
* The first not null value from the following is returned:
*
* - the value of the parameter
* - the thread local file resolver
* - the global file resolver
*
*
* @param fileRes a file resolver that will be returned if not null
* @return a file resolver
* @see #setGlobalFileResolver(FileResolver)
* @see #setThreadFileResolver(FileResolver)
*/
public static FileResolver getFileResolver(FileResolver fileRes)
{
FileResolver fileResolver = fileRes;
if (fileResolver == null)
{
fileResolver = getThreadFileResolver();
if (fileResolver == null)
{
fileResolver = globalFileResolver;
}
}
return fileResolver;
}
/**
* Returns the global file resolver.
*
* @return the global file resolver
* @see #setGlobalFileResolver(FileResolver)
*/
public static FileResolver getGlobalFileResolver()
{
return globalFileResolver;
}
/**
* Returns the thread local file resolver.
*
* @return the thread local file resolver.
* @see #setThreadFileResolver(FileResolver)
*/
public static FileResolver getThreadFileResolver()
{
return (FileResolver) localFileResolverStack.top();
}
/**
* Sets the thread local file resolver.
*
* @param fileResolver a file resolver.
* @see #getFileResolver(FileResolver)
* @see #resetThreadFileResolver()
*/
public static void setThreadFileResolver(FileResolver fileResolver)
{
localFileResolverStack.push(fileResolver);
}
/**
* Resets the the thread local file resolver to its previous value.
*/
public static void resetThreadFileResolver()
{
localFileResolverStack.pop();
}
/**
* Sets a global file resolver to be used for file resolution.
*
* @param fileResolver the file resolver
* @see #getFileResolver(FileResolver)
*/
public static void setGlobalFileResolver(FileResolver fileResolver)
{
globalFileResolver = fileResolver;
}
/**
* Attempts to find a file using a file resolver.
*
* @param location file name
* @param fileRes a file resolver
* @return the file, if found
*/
public static File resolveFile(String location, FileResolver fileRes)
{
FileResolver fileResolver = getFileResolver(fileRes);
if (fileResolver != null)
{
return fileResolver.resolveFile(location);
}
File file = new File(location);
if (file.exists() && file.isFile())
{
return file;
}
return null;
}
/**
* Returns an URL steam handler factory.
*
* The first not null value from the following is returned:
*
* - the value of the parameter
* - the thread local URL stream handler factory
* - the global URL stream handler factory
*
*
* @param urlHandlerFact an URL steam handler factory that will be returned if not null
* @return an URL steam handler factory
* @see #setGlobalURLHandlerFactory(URLStreamHandlerFactory)
* @see #setThreadURLHandlerFactory(URLStreamHandlerFactory)
*/
public static URLStreamHandlerFactory getURLHandlerFactory(URLStreamHandlerFactory urlHandlerFact)
{
URLStreamHandlerFactory urlHandlerFactory = urlHandlerFact;
if (urlHandlerFactory == null)
{
urlHandlerFactory = getThreadURLStreamHandlerFactory();
if (urlHandlerFactory == null)
{
urlHandlerFactory = globalURLHandlerFactory;
}
}
return urlHandlerFactory;
}
/**
* Returns the global URL stream handler factory.
*
* @return the global URL stream handler factory
* @see #setGlobalURLHandlerFactory(URLStreamHandlerFactory)
*/
public static URLStreamHandlerFactory getGlobalURLStreamHandlerFactory()
{
return globalURLHandlerFactory;
}
/**
* Returns the thread local URL stream handler factory.
*
* @return the thread local URL stream handler factory.
* @see #setThreadURLHandlerFactory(URLStreamHandlerFactory)
*/
public static URLStreamHandlerFactory getThreadURLStreamHandlerFactory()
{
return (URLStreamHandlerFactory) localURLHandlerFactoryStack.top();
}
/**
* Sets the thread local URL stream handler factory.
*
* @param urlHandlerFactory an URL stream handler factory.
* @see #getURLHandlerFactory(URLStreamHandlerFactory)
* @see #resetThreadURLHandlerFactory()
*/
public static void setThreadURLHandlerFactory(URLStreamHandlerFactory urlHandlerFactory)
{
localURLHandlerFactoryStack.push(urlHandlerFactory);
}
/**
* Resets the the thread local URL stream handler factory to its previous value.
*/
public static void resetThreadURLHandlerFactory()
{
localURLHandlerFactoryStack.pop();
}
/**
* Sets a global URL stream handler facotry to be used for resource resolution.
*
* @param urlHandlerFactory the URL stream handler factory
* @see #getURLHandlerFactory(URLStreamHandlerFactory)
*/
public static void setGlobalURLHandlerFactory(URLStreamHandlerFactory urlHandlerFactory)
{
globalURLHandlerFactory = urlHandlerFactory;
}
/**
* Returns a class loader.
*
* The first not null value from the following is returned:
*
* - the value of the parameter
* - the thread local class loader
* - the global class loader
*
*
* @param clsLoader a class loader that will be returned if not null
* @return a class loader.
* @see #setGlobalClassLoader(ClassLoader)
* @see #setThreadClassLoader(ClassLoader)
*/
public static ClassLoader getClassLoader(ClassLoader clsLoader)
{
ClassLoader classLoader = clsLoader;
if (classLoader == null)
{
classLoader = getThreadClassLoader();
if (classLoader == null)
{
classLoader = globalClassLoader;
}
}
return classLoader;
}
/**
* Returns the global class loader.
*
* @return the global class loader.
* @see #setGlobalClassLoader(ClassLoader)
*/
public static ClassLoader getGlobalClassLoader()
{
return globalClassLoader;
}
/**
* Returns the thread local class loader.
*
* @return the thread local class loader.
* @see #setThreadClassLoader(ClassLoader)
*/
public static ClassLoader getThreadClassLoader()
{
return (ClassLoader) localClassLoaderStack.top();
}
/**
* Sets the thread local class loader.
*
* @param classLoader a class loader
* @see #getClassLoader(ClassLoader)
* @see #resetThreadURLHandlerFactory()
*/
public static void setThreadClassLoader(ClassLoader classLoader)
{
localClassLoaderStack.push(classLoader);
}
/**
* Resets the the thread local class loader to its previous value.
*/
public static void resetClassLoader()
{
localClassLoaderStack.pop();
}
/**
* Sets a global class loader to be used for resource resolution.
*
* @param classLoader the class loader
* @see #getClassLoader(ClassLoader)
*/
public static void setGlobalClassLoader(ClassLoader classLoader)
{
globalClassLoader = classLoader;
}
/**
* Attempts to find a resource using a class loader.
*
* The following sources are tried:
*
* - the class loader returned by {@link #getClassLoader(ClassLoader)
getClassLoader(classLoader)
}
* - the context class loader
* clazz.getClassLoader()
* clazz.getResource()
*
*
* @param location the resource name
* @param clsLoader a class loader
* @param clazz a class
* @return the resource URL if found
*/
public static URL findClassLoaderResource(String location, ClassLoader clsLoader, Class clazz)
{
ClassLoader classLoader = getClassLoader(clsLoader);
URL url = null;
if (classLoader != null)
{
url = classLoader.getResource(location);
}
if (url == null)
{
classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader != null)
{
url = classLoader.getResource(location);
}
if (url == null)
{
classLoader = clazz.getClassLoader();
if (classLoader == null)
{
url = clazz.getResource("/" + location);
}
else
{
url = classLoader.getResource(location);
}
}
}
return url;
}
/**
* Loads a resource bundle for a given base name and locale.
*
*
* This methods calls {@link #loadResourceBundle(String, Locale, ClassLoader)} with a null classloader.
*
*
* @param baseName the base name
* @param locale the locale
* @return the resource bundle for the given base name and locale
*/
public static ResourceBundle loadResourceBundle(String baseName, Locale locale)
{
return loadResourceBundle(baseName, locale, null);
}
/**
* Loads a resource bundle for a given base name and locale.
*
*
* The method attempts to load the resource bundle using the following classloaders
* (and stops at the first successful attempt):
*
* - the class loader returned by {@link #getClassLoader(ClassLoader)
getClassLoader(classLoader)
}
* - the context class loader
* JRClassLoader.class.getClassLoader()
*
*
*
* @param baseName the base name
* @param locale the locale
* @param clsLoader
* @return the resource bundle for the given base name and locale
* @see ResourceBundle#getBundle(String, Locale, ClassLoader)
*/
public static ResourceBundle loadResourceBundle(String baseName, Locale locale, ClassLoader clsLoader)
{
ResourceBundle resourceBundle = null;
ClassLoader classLoader = getClassLoader(clsLoader);
if (classLoader != null)
{
try
{
resourceBundle = ResourceBundle.getBundle(baseName, locale, classLoader);
}
catch (MissingResourceException e)
{
}
}
if (resourceBundle == null)
{
classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader != null)
{
try
{
resourceBundle = ResourceBundle.getBundle(baseName, locale, classLoader);
}
catch (MissingResourceException e)
{
}
}
}
if (resourceBundle == null)
{
classLoader = JRClassLoader.class.getClassLoader();
if (classLoader == null)
{
resourceBundle = ResourceBundle.getBundle(baseName, locale);
}
else
{
resourceBundle = ResourceBundle.getBundle(baseName, locale, classLoader);
}
}
return resourceBundle;
}
private JRResourcesUtil()
{
}
}