All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.jasperreports.engine.util.JRResourcesUtil Maven / Gradle / Ivy

There is a newer version: 6.21.3
Show newest version
/*
 * JasperReports - Free Java Reporting Library.
 * Copyright (C) 2001 - 2019 TIBCO Software Inc. 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.nio.file.InvalidPathException;
import java.nio.file.Paths;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.function.Function;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.repo.RepositoryContext;
import net.sf.jasperreports.repo.RepositoryResourceContext;
import net.sf.jasperreports.repo.RepositoryUtil;
import net.sf.jasperreports.repo.ResourceBundleResource;
import net.sf.jasperreports.repo.SimpleRepositoryContext;


/**
 * Provides methods for resource resolution via class loaders or URL stream handlers.
 * 
 * @author Lucian Chirita ([email protected])
 */
public final class JRResourcesUtil
{
	
	private static final Log log = LogFactory.getLog(JRResourcesUtil.class);
	
	/**
	 * 
	 */
	private static final String PROPERTIES_FILE_EXTENSION = ".properties";

	/** 
	 *
	 */
	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)
	 */
	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
	 */
	public static URLStreamHandler getURLHandler(String spec, URLStreamHandlerFactory urlHandlerFact)
	{
		URLStreamHandlerFactory urlHandlerFactory = urlHandlerFact;//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;
	}

	
	/**
	 * Attempts to find a file using a file resolver.
	 * 
	 * @param location file name
	 * @param fileRes a file resolver
	 * @return the file, if found
	 * @deprecated To be removed.
	 */
	public static File resolveFile(String location, FileResolver fileRes)
	{
		FileResolver fileResolver = fileRes;//getFileResolver(fileRes);
		
		if (fileResolver != null)
		{
			return fileResolver.resolveFile(location);
		}

		return resolveFile(null, location);
	}


	public static File resolveFile(RepositoryContext context, String location)
	{
		return resolveFile(context, location, JRResourcesUtil::defaultLocateFile);
	}

	public static File resolveFile(RepositoryContext context, String location, Function rootLocator)
	{
		File file = locateFile(context == null ? null : context.getResourceContext(), location, rootLocator);
		if (file != null && file.isFile())
		{
			return file;
		}
		
		return null;
	}
	
	protected static File defaultLocateFile(String location)
	{
		File file = new File(location);
		if (file.exists())
		{
			return file;
		}
		
		return null;
	}
	
	protected static File locateFile(RepositoryResourceContext resourceContext, String location, Function rootLocator)
	{
		File file = rootLocator.apply(location);
		if (file != null)
		{
			return file;
		}
		
		if (resourceContext != null)
		{
			RepositoryResourceContext context = resourceContext;
			while (context != null)
			{
				File contextDir = locateContextDirectory(context, rootLocator);
				if (contextDir != null)
				{
					file = new File(contextDir, location);
					if (file.exists())
					{
						if (log.isDebugEnabled())
						{
							log.debug("resolved location " + location + " relative to the context " + contextDir);
						}
						
						return file;
					}
				}
				
				context = context.getFallbackContext();
			}
		}
		
		return null;
	}

	protected static File locateContextDirectory(RepositoryResourceContext resourceContext, Function rootLocator)
	{
		String contextLocation = resourceContext.getContextLocation();
		if (contextLocation != null)
		{
			try
			{
				Paths.get(contextLocation);//valid patch check
				File contextDir = rootLocator.apply(contextLocation);
				if (contextDir != null && contextDir.isDirectory())
				{
					return contextDir;
				}
			}
			catch (InvalidPathException e)
			{
				if (log.isDebugEnabled())
				{
					log.debug("location \"" + contextLocation + "\" is not a file path: " + e);
				}
			}
		}
		return null;
	}


	/**
	 * 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) */ 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 * @deprecated Replaced by {@link #findClassLoaderResource(String, ClassLoader)}. */ 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; } /** * 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
  • *
  • JRLoader.class.getClassLoader()
  • *
  • JRLoader.class.getResource()
  • *
* * @param location the resource name * @param clsLoader a class loader * @return the resource URL if found */ public static URL findClassLoaderResource(String location, ClassLoader clsLoader) { 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 = JRLoader.class.getClassLoader(); if (classLoader == null) { url = JRLoader.class.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(JasperReportsContext jasperReportsContext, String baseName, Locale locale) { return loadResourceBundle(SimpleRepositoryContext.of(jasperReportsContext), baseName, locale); } public static ResourceBundle loadResourceBundle(RepositoryContext repositoryContext, String baseName, Locale locale) { ResourceBundle resourceBundle = null; MissingResourceException ex = null; try { resourceBundle = loadResourceBundle(baseName, locale, null); } catch (MissingResourceException e) { ex = e; } if (resourceBundle == null) { CustomControl control = new CustomControl(); List locales = control.getCandidateLocales(baseName, locale); for (Locale lc : locales) { String suffix = lc.toString(); suffix = (suffix.trim().length() > 0 ? "_" : "") + suffix; ResourceBundleResource resourceBundleResource = null; try { resourceBundleResource = RepositoryUtil.getInstance(repositoryContext).getResourceFromLocation( baseName + suffix + PROPERTIES_FILE_EXTENSION, ResourceBundleResource.class ); } catch (JRException e) { } if (resourceBundleResource != null) { resourceBundle = resourceBundleResource.getResourceBundle(); break; } } } if (resourceBundle == null) { throw ex; } return resourceBundle; } /** * 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() { } } /** * */ class CustomControl extends ResourceBundle.Control { public CustomControl() { } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy