/* * 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 <http://www.gnu.org/licenses/>. */ package net.sf.jasperreports.engine.util; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLStreamHandlerFactory; import java.util.ArrayList; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRRuntimeException; /** * @author Teodor Danciu (teodord@users.sourceforge.net) * @version $Id: JRLoader.java 3845 2010-06-01 12:15:15Z lucianc $ */ public final class JRLoader { private static final Log log = LogFactory.getLog(JRLoader.class); /** * */ //private static boolean wasWarning = false; /** * */ public static Object loadObject(String fileName) throws JRException { return loadObject(new File(fileName)); } /** * */ public static Object loadObject(File file) throws JRException { if (!file.exists() || !file.isFile()) { throw new JRException( new FileNotFoundException(String.valueOf(file)) ); } Object obj = null; FileInputStream fis = null; ObjectInputStream ois = null; try { fis = new FileInputStream(file); BufferedInputStream bufferedIn = new BufferedInputStream(fis); ois = new ContextClassLoaderObjectInputStream(bufferedIn); obj = ois.readObject(); } catch (IOException e) { throw new JRException("Error loading object from file : " + file, e); } catch (ClassNotFoundException e) { throw new JRException("Class not found when loading object from file : " + file, e); } finally { if (ois != null) { try { ois.close(); } catch(IOException e) { } } if (fis != null) { try { fis.close(); } catch(IOException e) { } } } return obj; } /** * */ public static Object loadObject(URL url) throws JRException { Object obj = null; InputStream is = null; ObjectInputStream ois = null; try { is = url.openStream(); ois = new ContextClassLoaderObjectInputStream(is); obj = ois.readObject(); } catch (IOException e) { throw new JRException("Error loading object from URL : " + url, e); } catch (ClassNotFoundException e) { throw new JRException("Class not found when loading object from URL : " + url, e); } finally { if (ois != null) { try { ois.close(); } catch(IOException e) { } } if (is != null) { try { is.close(); } catch(IOException e) { } } } return obj; } /** * */ public static Object loadObject(InputStream is) throws JRException { Object obj = null; ObjectInputStream ois = null; try { ois = new ContextClassLoaderObjectInputStream(is); obj = ois.readObject(); } catch (IOException e) { throw new JRException("Error loading object from InputStream", e); } catch (ClassNotFoundException e) { throw new JRException("Class not found when loading object from InputStream", e); } return obj; } /** * */ public static Object loadObjectFromLocation(String location) throws JRException { return loadObjectFromLocation(location, null, null, null); } /** * */ public static Object loadObjectFromLocation(String location, ClassLoader classLoader) throws JRException { return loadObjectFromLocation(location, classLoader, null, null); } /** * */ public static Object loadObjectFromLocation( String location, ClassLoader classLoader, URLStreamHandlerFactory urlHandlerFactory, FileResolver fileResolver ) throws JRException { URL url = JRResourcesUtil.createURL(location, urlHandlerFactory); if (url != null) { return loadObject(url); } File file = JRResourcesUtil.resolveFile(location, fileResolver); if (file != null) { return loadObject(file); } url = JRResourcesUtil.findClassLoaderResource(location, classLoader, JRLoader.class); if (url != null) { return loadObject(url); } throw new JRException("Could not load object from location : " + location); } /** * */ public static byte[] loadBytes(File file) throws JRException { ByteArrayOutputStream baos = null; FileInputStream fis = null; try { fis = new FileInputStream(file); baos = new ByteArrayOutputStream(); byte[] bytes = new byte[10000]; int ln = 0; while ((ln = fis.read(bytes)) > 0) { baos.write(bytes, 0, ln); } baos.flush(); } catch (IOException e) { throw new JRException("Error loading byte data : " + file, e); } finally { if (baos != null) { try { baos.close(); } catch(IOException e) { } } if (fis != null) { try { fis.close(); } catch(IOException e) { } } } return baos.toByteArray(); } /** * */ public static byte[] loadBytes(URL url) throws JRException { ByteArrayOutputStream baos = null; InputStream is = null; try { is = url.openStream(); baos = new ByteArrayOutputStream(); byte[] bytes = new byte[10000]; int ln = 0; while ((ln = is.read(bytes)) > 0) { baos.write(bytes, 0, ln); } baos.flush(); } catch (IOException e) { throw new JRException("Error loading byte data : " + url, e); } finally { if (baos != null) { try { baos.close(); } catch(IOException e) { } } if (is != null) { try { is.close(); } catch(IOException e) { } } } return baos.toByteArray(); } /** * */ public static byte[] loadBytes(InputStream is) throws JRException { ByteArrayOutputStream baos = null; try { baos = new ByteArrayOutputStream(); byte[] bytes = new byte[10000]; int ln = 0; while ((ln = is.read(bytes)) > 0) { baos.write(bytes, 0, ln); } baos.flush(); } catch (IOException e) { throw new JRException("Error loading byte data from input stream.", e); } finally { if (baos != null) { try { baos.close(); } catch(IOException e) { } } } return baos.toByteArray(); } /** * */ public static byte[] loadBytesFromLocation(String location) throws JRException { return loadBytesFromLocation(location, null, null, null); } /** * */ public static byte[] loadBytesFromLocation(String location, ClassLoader classLoader) throws JRException { return loadBytesFromLocation(location, classLoader, null, null); } /** * */ public static byte[] loadBytesFromLocation( String location, ClassLoader classLoader, URLStreamHandlerFactory urlHandlerFactory ) throws JRException { return loadBytesFromLocation(location, classLoader, urlHandlerFactory, null); } /** * */ public static byte[] loadBytesFromLocation( String location, ClassLoader classLoader, URLStreamHandlerFactory urlHandlerFactory, FileResolver fileResolver ) throws JRException { URL url = JRResourcesUtil.createURL(location, urlHandlerFactory); if (url != null) { return loadBytes(url); } File file = JRResourcesUtil.resolveFile(location, fileResolver); if (file != null) { return loadBytes(file); } url = JRResourcesUtil.findClassLoaderResource(location, classLoader, JRLoader.class); if (url != null) { return loadBytes(url); } throw new JRException("Byte data not found at location : " + location); } /** * Tries to open an input stream for a location. * <p> * The method tries to interpret the location as a file name, a resource name or * an URL. If any of these succeed, an input stream is created and returned. * * @param location the location * @return an input stream if the location is an existing file name, a resource name on * the classpath or an URL or <code>null</code> otherwise. * * @throws JRException */ public static InputStream getLocationInputStream(String location) throws JRException { InputStream is = null; is = getResourceInputStream(location); if (is == null) { is = getFileInputStream(location); } if (is == null) { is = getURLInputStream(location); } return is; } /** * Tries to open a file for reading. * * @param filename the file name * @return an input stream for the file or <code>null</code> if the file was not found * @throws JRException */ public static InputStream getFileInputStream(String filename) throws JRException { InputStream is = null; File file = new File(filename); if (file.exists() && file.isFile()) { try { is = new FileInputStream(file); } catch (FileNotFoundException e) { throw new JRException("Error opening file " + filename, e); } } return is; } /** * Tries to open an input stream for a resource. * * @param resource the resource name * @return an input stream for the resource or <code>null</code> if the resource was not found */ public static InputStream getResourceInputStream(String resource) { InputStream is = null; ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader != null) { is = classLoader.getResourceAsStream(resource); } if (is == null) { classLoader = JRLoader.class.getClassLoader(); if (classLoader != null) { is = classLoader.getResourceAsStream(resource); } if (is == null) { is = JRProperties.class.getResourceAsStream("/" + resource); } } return is; } /** * Scans the context classloader and the classloader of this class for all * resources that have a specified name, and returns a list of * {@link URL}s for the found resources. * * @param resource the resource names * @return a list of {@link URL}s of resources with the specified name; * the list is empty if no resources have been found for the name * @see ClassLoader#getResources(String) */ public static List<URL> getResources(String resource) { //skip duplicated resources Set<URL> resources = new LinkedHashSet<URL>(); collectResources(resource, JRLoader.class.getClassLoader(), resources); collectResources(resource, Thread.currentThread().getContextClassLoader(), resources); return new ArrayList(resources); } protected static void collectResources(String resourceName, ClassLoader classLoader, Set<URL> resources) { if (classLoader != null) { try { for (Enumeration<URL> urls = classLoader.getResources(resourceName); urls.hasMoreElements();) { URL url = urls.nextElement(); resources.add(url); } } catch (IOException e) { throw new JRRuntimeException(e); } } } /** * Scans the context classloader and the classloader of this class for all * resources that have a specified name, and returns a list of * {@link ClassLoaderResource} objects for the found resources. * * <p> * The returned list contains the URLs of the resources, and for each resource * the highest classloader in the classloader hierarchy on which the resource * was found. * </p> * * @param resource the resource names * @return a list of resources with the specified name; * the list is empty if no resources have been found for the name * @see ClassLoader#getResources(String) */ public static List<ClassLoaderResource> getClassLoaderResources( String resource) { Map<URL, ClassLoaderResource> resources = new LinkedHashMap<URL, ClassLoaderResource>(); collectResources(resource, JRLoader.class.getClassLoader(), resources); //TODO check if the classloader is the same collectResources(resource, Thread.currentThread() .getContextClassLoader(), resources); return new ArrayList<ClassLoaderResource>(resources.values()); } protected static void collectResources(String resourceName, ClassLoader classLoader, Map<URL, ClassLoaderResource> resources) { if (classLoader == null) { return; } try { // creating a list of parent classloaders, with the highest in the // hierarchy first LinkedList<ClassLoader> classloaders = new LinkedList<ClassLoader>(); ClassLoader ancestorLoader = classLoader; while (ancestorLoader != null) { classloaders.addFirst(ancestorLoader); try { ancestorLoader = ancestorLoader.getParent(); } catch (SecurityException e) { // if we're not allowed to get the parent, stop here. // resources will be listed with the first classloader that // we're allowed to access. // one case when this happens is applets. // FIXME revisit logging on SecurityException for applet ancestorLoader = null; } } for (ClassLoader ancestor : classloaders) { for (Enumeration<URL> urls = ancestor.getResources(resourceName); urls.hasMoreElements();) { URL url = urls.nextElement(); // if this is the first time we see this resource, add it // with the current classloader. // this way a resource will be added with the most first // ancestor classloader that has it. if (!resources.containsKey(url)) { if (log.isDebugEnabled()) { log.debug("Found resource " + resourceName + " at "+ url + " in classloader " + ancestor); } ClassLoaderResource resource = new ClassLoaderResource( url, ancestor); resources.put(url, resource); } } } } catch (IOException e) { throw new JRRuntimeException(e); } } /** * Returns the resource URL for a specified resource name. * * @param resource the resource name * @return the URL of the resource having the specified name, or * <code>null</code> if none found * @see ClassLoader#getResource(String) */ public static URL getResource(String resource) { URL location = null; ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader != null) { location = classLoader.getResource(resource); } if (location == null) { classLoader = JRLoader.class.getClassLoader(); if (classLoader != null) { location = classLoader.getResource(resource); } if (location == null) { location = JRProperties.class.getResource("/" + resource); } } return location; } /** * Tries to open an input stream for an URL. * * @param spec the string to parse as an URL * @return an input stream for the URL or null if <code>spec</code> is not a valid URL * @throws JRException */ public static InputStream getURLInputStream(String spec) throws JRException { InputStream is = null; try { URL url = new URL(spec); is = url.openStream(); } catch (MalformedURLException e) { } catch (IOException e) { throw new JRException("Error opening URL " + spec, e); } return is; } private JRLoader() { } }