/* * Copyright (C) 2011 Laurent Caillette * * This program 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. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.novelang.outfit.loader; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import com.google.common.base.Preconditions; import org.apache.commons.lang.SystemUtils; import org.novelang.logger.Logger; import org.novelang.logger.LoggerFactory; /** * Loads resources relative to the root package of some given class * using its classloader. * * @author Laurent Caillette */ public class ClasspathResourceLoader extends AbstractResourceLoader { private static final Logger LOGGER = LoggerFactory.getLogger( ClasspathResourceLoader.class ) ; private final Class reference ; private final String path ; private final String searchPathForDescription ; protected ClasspathResourceLoader( final Class reference, final String path ) { this.reference = Preconditions.checkNotNull( reference ) ; this.path = null == path ? "" : normalize( path ) ; searchPathForDescription = getBestDescriptorForClassloader() ; } public ClasspathResourceLoader() { this( ClasspathResourceLoader.class, null ) ; } public ClasspathResourceLoader( final String path ) { this( ClasspathResourceLoader.class, path ) ; } @Override protected String getMultilineDescription() { return toString() ; } @Override public String toString() { if( path == null ) { return getClass().getSimpleName() + "{classpath files and jars}" ; } else { return getClass().getSimpleName() + "{" + path + "}"; } } @Override public InputStream maybeGetInputStream( final ResourceName resourceName ) { final String absoluteName = path + "/" + resourceName.getName() ; // normalize( resourceName ) ; final URL url = reference.getResource( absoluteName ) ; if( null == url ) { return null ; } final String urlAsString = url.toExternalForm(); try { final InputStream inputStream = url.openStream(); LOGGER.info( "Opened stream '", urlAsString, "'." ) ; return inputStream; } catch( IOException e ) { throw new ResourceNotFoundException( absoluteName, getBestDescriptorForClassloader(), e ) ; } } /** * Force "/" at beginning, removes "/" at end. */ private static String normalize( final String path ) { String newPath = path ; if( ! path.startsWith( "/" ) ) { newPath = "/" + path ; } if( path.endsWith( "/" ) ) { newPath = path.substring( 0, path.length() - 1 ) ; } return newPath ; } private static final String SYSTEM_CLASSPATH = "file:" + SystemUtils.JAVA_HOME ; private String getBestDescriptorForClassloader() { final ClassLoader classLoader = getClass().getClassLoader(); final StringBuilder buffer = new StringBuilder( toString() ); if( classLoader instanceof URLClassLoader ) { final URLClassLoader urlClassLoader = ( URLClassLoader ) classLoader ; final URL[] urls = urlClassLoader.getURLs() ; for( final URL url : urls ) { final String urlAsString = url.toExternalForm(); if( ! urlAsString.startsWith( SYSTEM_CLASSPATH ) ) { buffer.append( "\n" ) ; buffer.append( " " ) ; buffer.append( urlAsString ) ; } } } else { buffer.append( " " ).append( classLoader.toString() ); } return buffer.toString() ; } }