package org.limewire.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.JarURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Enumeration; import java.util.UUID; import java.util.jar.JarEntry; import java.util.jar.JarFile; import com.google.inject.AbstractModule; import com.google.inject.Module; public class TestUtils { /** * Gets a resource using the class loader * or the system class loader. */ public static URL getResource(String location) { ClassLoader cl = TestUtils.class.getClassLoader(); URL resource = null; if(cl == null) { resource = ClassLoader.getSystemResource(location); } else { resource = cl.getResource(location); } return resource; } /** * Gets a resource stream using the class loader * or the system class loader. */ public static InputStream getResourceAsStream(String location) { ClassLoader cl = TestUtils.class.getClassLoader(); InputStream resource = null; if(cl == null) { resource = ClassLoader.getSystemResourceAsStream(location); } else { resource = cl.getResourceAsStream(location); } return resource; } /** * Gets a resource file using the class loader * or the system class loader. */ public static File getResourceFile(String location) { URL resource = getResource(location); if( resource == null ) { // note: this will probably not work, // but it will ultimately trigger a better exception // than returning null. return new File(location); } // if the resource exited inside a jar, let's create a temporary file for the world to use. // (we must convert path characters to the same character in order to check) String resourceString = resource.toString(); resourceString = resourceString.replace("\\", "/"); location = location.replace("\\", "/"); if(resourceString.startsWith("jar:file:") && resourceString.endsWith("!/" + location)) { File tmpFile; try { tmpFile = File.createTempFile("jarTmp", "lwTestTmp"); tmpFile.deleteOnExit(); InputStream stream = resource.openStream(); CommonUtils.saveStream(stream, tmpFile); return tmpFile; } catch(Throwable iox) { throw new RuntimeException("failed to expand jar resource file: " + location, iox); } } if(resourceString.startsWith("jar:file")) { throw new RuntimeException("resource[" + location + "] is inside jar and cannot be expanded"); } //NOTE: The resource URL will contain %20 instead of spaces. // This is by design, but will not work when trying to make a file. // See BugParadeID: 4466485 //(http://developer.java.sun.com/developer/bugParade/bugs/4466485.html) // The recommended workaround is to use the URI class, but that doesn't // exist until Java 1.4. So, we can't use it here. // Thus, we manually have to parse out the %20s from the URL return new File( CommonUtils.decode(resource.getFile()) ); } /** * This method will find a jar with the given resource path and will extract the * contents from the first jar it finds that matches that path into a unique temporary * directory. Callers should delete the directory when they are done using it. * <p> * If the resource is found in the classpath as not a jar, then the resources are instead * copied to the unique temp directory. */ public static File extractResourceDirectory(String location) throws IOException { File efile = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString()); URL url = ClassLoader.getSystemResource(location); URLConnection urlConnection = url.openConnection(); if(JarURLConnection.class.isInstance(urlConnection)) { //if it is a jar file we want to extract files in the directory we need JarURLConnection jarConnection = (JarURLConnection)urlConnection; JarFile jarFile = jarConnection.getJarFile(); for(Enumeration<JarEntry> entires = jarFile.entries(); entires.hasMoreElements();) { JarEntry entry = entires.nextElement(); String name = entry.getName(); if(!entry.isDirectory() && name.startsWith(location)) { InputStream in = null; OutputStream out = null; try { in = new BufferedInputStream(jarFile.getInputStream(entry)); String outFileName = name.substring(location.length()); File outFile = new File(efile, outFileName); outFile.getParentFile().mkdirs(); out = new BufferedOutputStream(new FileOutputStream(outFile)); FileUtils.write(in, out); } finally { FileUtils.close(in); FileUtils.close(out); } } } } else { //if it is on the filesystem already we can just copy the directory we need File resourceDir = getResourceFile(location); FileUtils.copyDirectory(resourceDir, efile); } return efile; } public static File getResourceInPackage(String resourceName, Class nearResource) { String name = nearResource.getPackage().getName().replace(".", "/"); return getResourceFile(name + "/" + resourceName); } public static <T, F extends T> Module createInstanceModule(final Class<T> interfaze, final F implemenation) { return new AbstractModule() { @Override protected void configure() { bind(interfaze).toInstance(implemenation); } }; } /** * Experimental fluent interface to binding test classes. */ public static To bind(Class... interfaces) { return new To(interfaces); } public static class To { private final Class[] interfaces; public To(Class...interfaces) { this.interfaces = interfaces; } public Module to(final Class... implementations) { if (interfaces.length != implementations.length) { throw new IllegalArgumentException("length of interfaces doesn't not match implementations"); } return new AbstractModule() { @SuppressWarnings("unchecked") @Override protected void configure() { for (int i = 0; i < interfaces.length; i++) { bind(interfaces[i]).to(implementations[i]); } } }; } public Module toInstances(final Object...instances) { if (interfaces.length != instances.length) { throw new IllegalArgumentException("length of interfaces doesn't not match instances"); } return new AbstractModule() { @SuppressWarnings("unchecked") @Override protected void configure() { for (int i = 0; i < interfaces.length; i++) { bind(interfaces[i]).toInstance(instances[i]); } } }; } } public static void main(String[] args) throws IOException { System.out.println(TestUtils.extractResourceDirectory("com/google/inject")); } }