| /* |
| * Copyright (C) 2012 The Guava Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.common.reflect; |
| |
| import static com.google.common.base.Charsets.US_ASCII; |
| import static com.google.common.base.StandardSystemProperty.JAVA_CLASS_PATH; |
| import static com.google.common.base.StandardSystemProperty.PATH_SEPARATOR; |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.io.Closer; |
| import com.google.common.io.Files; |
| import com.google.common.io.Resources; |
| import com.google.common.reflect.ClassPath.ClassInfo; |
| import com.google.common.reflect.ClassPath.ResourceInfo; |
| import com.google.common.testing.EqualsTester; |
| import com.google.common.testing.NullPointerTester; |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.FilePermission; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.MalformedURLException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.net.URLClassLoader; |
| import java.security.Permission; |
| import java.security.PermissionCollection; |
| import java.util.Enumeration; |
| import java.util.HashSet; |
| import java.util.Set; |
| import java.util.jar.Attributes; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarFile; |
| import java.util.jar.JarOutputStream; |
| import java.util.jar.Manifest; |
| import java.util.logging.Logger; |
| import java.util.zip.ZipEntry; |
| import junit.framework.TestCase; |
| import org.junit.Test; |
| |
| /** Functional tests of {@link ClassPath}. */ |
| public class ClassPathTest extends TestCase { |
| private static final Logger log = Logger.getLogger(ClassPathTest.class.getName()); |
| |
| public void testEquals() { |
| new EqualsTester() |
| .addEqualityGroup(classInfo(ClassPathTest.class), classInfo(ClassPathTest.class)) |
| .addEqualityGroup(classInfo(Test.class), classInfo(Test.class, getClass().getClassLoader())) |
| .addEqualityGroup( |
| new ResourceInfo("a/b/c.txt", getClass().getClassLoader()), |
| new ResourceInfo("a/b/c.txt", getClass().getClassLoader())) |
| .addEqualityGroup(new ResourceInfo("x.txt", getClass().getClassLoader())) |
| .testEquals(); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| public void testClassPathEntries_emptyURLClassLoader_noParent() { |
| assertThat(ClassPath.Scanner.getClassPathEntries(new URLClassLoader(new URL[0], null)).keySet()) |
| .isEmpty(); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| public void testClassPathEntries_URLClassLoader_noParent() throws Exception { |
| URL url1 = new URL("file:/a"); |
| URL url2 = new URL("file:/b"); |
| URLClassLoader classloader = new URLClassLoader(new URL[] {url1, url2}, null); |
| assertThat(ClassPath.Scanner.getClassPathEntries(classloader)) |
| .containsExactly(new File("/a"), classloader, new File("/b"), classloader); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| public void testClassPathEntries_URLClassLoader_withParent() throws Exception { |
| URL url1 = new URL("file:/a"); |
| URL url2 = new URL("file:/b"); |
| URLClassLoader parent = new URLClassLoader(new URL[] {url1}, null); |
| URLClassLoader child = new URLClassLoader(new URL[] {url2}, parent) {}; |
| assertThat(ClassPath.Scanner.getClassPathEntries(child)) |
| .containsExactly(new File("/a"), parent, new File("/b"), child) |
| .inOrder(); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| public void testClassPathEntries_duplicateUri_parentWins() throws Exception { |
| URL url = new URL("file:/a"); |
| URLClassLoader parent = new URLClassLoader(new URL[] {url}, null); |
| URLClassLoader child = new URLClassLoader(new URL[] {url}, parent) {}; |
| assertThat(ClassPath.Scanner.getClassPathEntries(child)) |
| .containsExactly(new File("/a"), parent); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| public void testClassPathEntries_notURLClassLoader_noParent() { |
| assertThat(ClassPath.Scanner.getClassPathEntries(new ClassLoader(null) {})).isEmpty(); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| public void testClassPathEntries_notURLClassLoader_withParent() throws Exception { |
| URL url = new URL("file:/a"); |
| URLClassLoader parent = new URLClassLoader(new URL[] {url}, null); |
| assertThat(ClassPath.Scanner.getClassPathEntries(new ClassLoader(parent) {})) |
| .containsExactly(new File("/a"), parent); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| public void testClassPathEntries_notURLClassLoader_withParentAndGrandParent() throws Exception { |
| URL url1 = new URL("file:/a"); |
| URL url2 = new URL("file:/b"); |
| URLClassLoader grandParent = new URLClassLoader(new URL[] {url1}, null); |
| URLClassLoader parent = new URLClassLoader(new URL[] {url2}, grandParent); |
| assertThat(ClassPath.Scanner.getClassPathEntries(new ClassLoader(parent) {})) |
| .containsExactly(new File("/a"), grandParent, new File("/b"), parent); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| public void testClassPathEntries_notURLClassLoader_withGrandParent() throws Exception { |
| URL url = new URL("file:/a"); |
| URLClassLoader grandParent = new URLClassLoader(new URL[] {url}, null); |
| ClassLoader parent = new ClassLoader(grandParent) {}; |
| assertThat(ClassPath.Scanner.getClassPathEntries(new ClassLoader(parent) {})) |
| .containsExactly(new File("/a"), grandParent); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| // https://github.com/google/guava/issues/2152 |
| public void testClassPathEntries_URLClassLoader_pathWithSpace() throws Exception { |
| URL url = new URL("file:///c:/Documents and Settings/"); |
| URLClassLoader classloader = new URLClassLoader(new URL[] {url}, null); |
| assertThat(ClassPath.Scanner.getClassPathEntries(classloader)) |
| .containsExactly(new File("/c:/Documents and Settings/"), classloader); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| // https://github.com/google/guava/issues/2152 |
| public void testClassPathEntries_URLClassLoader_pathWithEscapedSpace() throws Exception { |
| URL url = new URL("file:///c:/Documents%20and%20Settings/"); |
| URLClassLoader classloader = new URLClassLoader(new URL[] {url}, null); |
| assertThat(ClassPath.Scanner.getClassPathEntries(classloader)) |
| .containsExactly(new File("/c:/Documents and Settings/"), classloader); |
| } |
| |
| // https://github.com/google/guava/issues/2152 |
| public void testToFile() throws Exception { |
| assertThat(ClassPath.toFile(new URL("file:///c:/Documents%20and%20Settings/"))) |
| .isEqualTo(new File("/c:/Documents and Settings/")); |
| assertThat(ClassPath.toFile(new URL("file:///c:/Documents ~ Settings, or not/11-12 12:05"))) |
| .isEqualTo(new File("/c:/Documents ~ Settings, or not/11-12 12:05")); |
| } |
| |
| // https://github.com/google/guava/issues/2152 |
| @AndroidIncompatible // works in newer Android versions but fails at the version we test with |
| public void testToFile_AndroidIncompatible() throws Exception { |
| assertThat(ClassPath.toFile(new URL("file:///c:\\Documents ~ Settings, or not\\11-12 12:05"))) |
| .isEqualTo(new File("/c:\\Documents ~ Settings, or not\\11-12 12:05")); |
| assertThat(ClassPath.toFile(new URL("file:///C:\\Program Files\\Apache Software Foundation"))) |
| .isEqualTo(new File("/C:\\Program Files\\Apache Software Foundation/")); |
| assertThat(ClassPath.toFile(new URL("file:///C:\\\u20320 \u22909"))) // Chinese Ni Hao |
| .isEqualTo(new File("/C:\\\u20320 \u22909")); |
| } |
| |
| @AndroidIncompatible // Android forbids null parent ClassLoader |
| // https://github.com/google/guava/issues/2152 |
| public void testJarFileWithSpaces() throws Exception { |
| URL url = makeJarUrlWithName("To test unescaped spaces in jar file name.jar"); |
| URLClassLoader classloader = new URLClassLoader(new URL[] {url}, null); |
| assertThat(ClassPath.from(classloader).getTopLevelClasses()).isNotEmpty(); |
| } |
| |
| public void testScan_classPathCycle() throws IOException { |
| File jarFile = File.createTempFile("with_circular_class_path", ".jar"); |
| try { |
| writeSelfReferencingJarFile(jarFile, "test.txt"); |
| ClassPath.DefaultScanner scanner = new ClassPath.DefaultScanner(); |
| scanner.scan(jarFile, ClassPathTest.class.getClassLoader()); |
| assertThat(scanner.getResources()).hasSize(1); |
| } finally { |
| jarFile.delete(); |
| } |
| } |
| |
| public void testScanFromFile_fileNotExists() throws IOException { |
| ClassLoader classLoader = ClassPathTest.class.getClassLoader(); |
| ClassPath.DefaultScanner scanner = new ClassPath.DefaultScanner(); |
| scanner.scan(new File("no/such/file/anywhere"), classLoader); |
| assertThat(scanner.getResources()).isEmpty(); |
| } |
| |
| public void testScanFromFile_notJarFile() throws IOException { |
| ClassLoader classLoader = ClassPathTest.class.getClassLoader(); |
| File notJar = File.createTempFile("not_a_jar", "txt"); |
| ClassPath.DefaultScanner scanner = new ClassPath.DefaultScanner(); |
| try { |
| scanner.scan(notJar, classLoader); |
| } finally { |
| notJar.delete(); |
| } |
| assertThat(scanner.getResources()).isEmpty(); |
| } |
| |
| public void testGetClassPathEntry() throws MalformedURLException, URISyntaxException { |
| assertEquals( |
| new File("/usr/test/dep.jar").toURI(), |
| ClassPath.Scanner.getClassPathEntry( |
| new File("/home/build/outer.jar"), "file:/usr/test/dep.jar") |
| .toURI()); |
| assertEquals( |
| new File("/home/build/a.jar").toURI(), |
| ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "a.jar").toURI()); |
| assertEquals( |
| new File("/home/build/x/y/z").toURI(), |
| ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z").toURI()); |
| assertEquals( |
| new File("/home/build/x/y/z.jar").toURI(), |
| ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x/y/z.jar") |
| .toURI()); |
| assertEquals( |
| "/home/build/x y.jar", |
| ClassPath.Scanner.getClassPathEntry(new File("/home/build/outer.jar"), "x y.jar") |
| .getFile()); |
| } |
| |
| public void testGetClassPathFromManifest_nullManifest() { |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(new File("some.jar"), null)).isEmpty(); |
| } |
| |
| public void testGetClassPathFromManifest_noClassPath() throws IOException { |
| File jarFile = new File("base.jar"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest(""))).isEmpty(); |
| } |
| |
| public void testGetClassPathFromManifest_emptyClassPath() throws IOException { |
| File jarFile = new File("base.jar"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifestClasspath(""))) |
| .isEmpty(); |
| } |
| |
| public void testGetClassPathFromManifest_badClassPath() throws IOException { |
| File jarFile = new File("base.jar"); |
| Manifest manifest = manifestClasspath("nosuchscheme:an_invalid^path"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)).isEmpty(); |
| } |
| |
| public void testGetClassPathFromManifest_pathWithStrangeCharacter() throws IOException { |
| File jarFile = new File("base/some.jar"); |
| Manifest manifest = manifestClasspath("file:the^file.jar"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)) |
| .containsExactly(fullpath("base/the^file.jar")); |
| } |
| |
| public void testGetClassPathFromManifest_relativeDirectory() throws IOException { |
| File jarFile = new File("base/some.jar"); |
| // with/relative/directory is the Class-Path value in the mf file. |
| Manifest manifest = manifestClasspath("with/relative/dir"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)) |
| .containsExactly(fullpath("base/with/relative/dir")); |
| } |
| |
| public void testGetClassPathFromManifest_relativeJar() throws IOException { |
| File jarFile = new File("base/some.jar"); |
| // with/relative/directory is the Class-Path value in the mf file. |
| Manifest manifest = manifestClasspath("with/relative.jar"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)) |
| .containsExactly(fullpath("base/with/relative.jar")); |
| } |
| |
| public void testGetClassPathFromManifest_jarInCurrentDirectory() throws IOException { |
| File jarFile = new File("base/some.jar"); |
| // with/relative/directory is the Class-Path value in the mf file. |
| Manifest manifest = manifestClasspath("current.jar"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)) |
| .containsExactly(fullpath("base/current.jar")); |
| } |
| |
| public void testGetClassPathFromManifest_absoluteDirectory() throws IOException { |
| File jarFile = new File("base/some.jar"); |
| Manifest manifest = manifestClasspath("file:/with/absolute/dir"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)) |
| .containsExactly(fullpath("/with/absolute/dir")); |
| } |
| |
| public void testGetClassPathFromManifest_absoluteJar() throws IOException { |
| File jarFile = new File("base/some.jar"); |
| Manifest manifest = manifestClasspath("file:/with/absolute.jar"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)) |
| .containsExactly(fullpath("/with/absolute.jar")); |
| } |
| |
| public void testGetClassPathFromManifest_multiplePaths() throws IOException { |
| File jarFile = new File("base/some.jar"); |
| Manifest manifest = manifestClasspath("file:/with/absolute.jar relative.jar relative/dir"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)) |
| .containsExactly( |
| fullpath("/with/absolute.jar"), |
| fullpath("base/relative.jar"), |
| fullpath("base/relative/dir")) |
| .inOrder(); |
| } |
| |
| public void testGetClassPathFromManifest_leadingBlanks() throws IOException { |
| File jarFile = new File("base/some.jar"); |
| Manifest manifest = manifestClasspath(" relative.jar"); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)) |
| .containsExactly(fullpath("base/relative.jar")); |
| } |
| |
| public void testGetClassPathFromManifest_trailingBlanks() throws IOException { |
| File jarFile = new File("base/some.jar"); |
| Manifest manifest = manifestClasspath("relative.jar "); |
| assertThat(ClassPath.Scanner.getClassPathFromManifest(jarFile, manifest)) |
| .containsExactly(fullpath("base/relative.jar")); |
| } |
| |
| public void testGetClassName() { |
| assertEquals("abc.d.Abc", ClassPath.getClassName("abc/d/Abc.class")); |
| } |
| |
| public void testResourceInfo_of() { |
| assertEquals(ClassInfo.class, resourceInfo(ClassPathTest.class).getClass()); |
| assertEquals(ClassInfo.class, resourceInfo(ClassPath.class).getClass()); |
| assertEquals(ClassInfo.class, resourceInfo(Nested.class).getClass()); |
| } |
| |
| public void testGetSimpleName() { |
| ClassLoader classLoader = getClass().getClassLoader(); |
| assertEquals("Foo", new ClassInfo("Foo.class", classLoader).getSimpleName()); |
| assertEquals("Foo", new ClassInfo("a/b/Foo.class", classLoader).getSimpleName()); |
| assertEquals("Foo", new ClassInfo("a/b/Bar$Foo.class", classLoader).getSimpleName()); |
| assertEquals("", new ClassInfo("a/b/Bar$1.class", classLoader).getSimpleName()); |
| assertEquals("Foo", new ClassInfo("a/b/Bar$Foo.class", classLoader).getSimpleName()); |
| assertEquals("", new ClassInfo("a/b/Bar$1.class", classLoader).getSimpleName()); |
| assertEquals("Local", new ClassInfo("a/b/Bar$1Local.class", classLoader).getSimpleName()); |
| } |
| |
| public void testGetPackageName() { |
| assertEquals("", new ClassInfo("Foo.class", getClass().getClassLoader()).getPackageName()); |
| assertEquals( |
| "a.b", new ClassInfo("a/b/Foo.class", getClass().getClassLoader()).getPackageName()); |
| } |
| |
| // Test that ResourceInfo.urls() returns identical content to ClassLoader.getResources() |
| |
| public void testGetClassPathUrls() throws Exception { |
| String oldPathSeparator = PATH_SEPARATOR.value(); |
| String oldClassPath = JAVA_CLASS_PATH.value(); |
| System.setProperty(PATH_SEPARATOR.key(), ":"); |
| System.setProperty( |
| JAVA_CLASS_PATH.key(), |
| Joiner.on(":") |
| .join( |
| "relative/path/to/some.jar", |
| "/absolute/path/to/some.jar", |
| "relative/path/to/class/root", |
| "/absolute/path/to/class/root")); |
| try { |
| ImmutableList<URL> urls = ClassPath.Scanner.parseJavaClassPath(); |
| |
| assertThat(urls.get(0).getProtocol()).isEqualTo("file"); |
| assertThat(urls.get(0).getAuthority()).isNull(); |
| assertThat(urls.get(0).getPath()).endsWith("/relative/path/to/some.jar"); |
| |
| assertThat(urls.get(1)).isEqualTo(new URL("file:///absolute/path/to/some.jar")); |
| |
| assertThat(urls.get(2).getProtocol()).isEqualTo("file"); |
| assertThat(urls.get(2).getAuthority()).isNull(); |
| assertThat(urls.get(2).getPath()).endsWith("/relative/path/to/class/root"); |
| |
| assertThat(urls.get(3)).isEqualTo(new URL("file:///absolute/path/to/class/root")); |
| |
| assertThat(urls).hasSize(4); |
| } finally { |
| System.setProperty(PATH_SEPARATOR.key(), oldPathSeparator); |
| System.setProperty(JAVA_CLASS_PATH.key(), oldClassPath); |
| } |
| } |
| |
| private static boolean contentEquals(URL left, URL right) throws IOException { |
| return Resources.asByteSource(left).contentEquals(Resources.asByteSource(right)); |
| } |
| |
| private static class Nested {} |
| |
| public void testNulls() throws IOException { |
| new NullPointerTester().testAllPublicStaticMethods(ClassPath.class); |
| new NullPointerTester() |
| .testAllPublicInstanceMethods(ClassPath.from(getClass().getClassLoader())); |
| } |
| |
| public void testResourceScanner() throws IOException { |
| ResourceScanner scanner = new ResourceScanner(); |
| scanner.scan(ClassLoader.getSystemClassLoader()); |
| assertThat(scanner.resources).contains("com/google/common/reflect/ClassPathTest.class"); |
| } |
| |
| public void testExistsThrowsSecurityException() throws IOException, URISyntaxException { |
| SecurityManager oldSecurityManager = System.getSecurityManager(); |
| try { |
| doTestExistsThrowsSecurityException(); |
| } finally { |
| System.setSecurityManager(oldSecurityManager); |
| } |
| } |
| |
| private void doTestExistsThrowsSecurityException() throws IOException, URISyntaxException { |
| File file = null; |
| // In Java 9, Logger may read the TZ database. Only disallow reading the class path URLs. |
| final PermissionCollection readClassPathFiles = |
| new FilePermission("", "read").newPermissionCollection(); |
| for (URL url : ClassPath.Scanner.parseJavaClassPath()) { |
| if (url.getProtocol().equalsIgnoreCase("file")) { |
| file = new File(url.toURI()); |
| readClassPathFiles.add(new FilePermission(file.getAbsolutePath(), "read")); |
| } |
| } |
| assertThat(file).isNotNull(); |
| SecurityManager disallowFilesSecurityManager = |
| new SecurityManager() { |
| @Override |
| public void checkPermission(Permission p) { |
| if (readClassPathFiles.implies(p)) { |
| throw new SecurityException("Disallowed: " + p); |
| } |
| } |
| }; |
| System.setSecurityManager(disallowFilesSecurityManager); |
| try { |
| file.exists(); |
| fail("Did not get expected SecurityException"); |
| } catch (SecurityException expected) { |
| } |
| ClassPath classPath = ClassPath.from(getClass().getClassLoader()); |
| // ClassPath may contain resources from the boot class loader; just not from the class path. |
| for (ResourceInfo resource : classPath.getResources()) { |
| assertThat(resource.getResourceName()).doesNotContain("com/google/common/reflect/"); |
| } |
| } |
| |
| private static ClassPath.ClassInfo findClass( |
| Iterable<ClassPath.ClassInfo> classes, Class<?> cls) { |
| for (ClassPath.ClassInfo classInfo : classes) { |
| if (classInfo.getName().equals(cls.getName())) { |
| return classInfo; |
| } |
| } |
| throw new AssertionError("failed to find " + cls); |
| } |
| |
| private static ResourceInfo resourceInfo(Class<?> cls) { |
| String resource = cls.getName().replace('.', '/') + ".class"; |
| ClassLoader loader = cls.getClassLoader(); |
| return ResourceInfo.of(resource, loader); |
| } |
| |
| private static ClassInfo classInfo(Class<?> cls) { |
| return classInfo(cls, cls.getClassLoader()); |
| } |
| |
| private static ClassInfo classInfo(Class<?> cls, ClassLoader classLoader) { |
| String resource = cls.getName().replace('.', '/') + ".class"; |
| return new ClassInfo(resource, classLoader); |
| } |
| |
| private static Manifest manifestClasspath(String classpath) throws IOException { |
| return manifest("Class-Path: " + classpath + "\n"); |
| } |
| |
| private static void writeSelfReferencingJarFile(File jarFile, String... entries) |
| throws IOException { |
| Manifest manifest = new Manifest(); |
| // Without version, the manifest is silently ignored. Ugh! |
| manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); |
| manifest.getMainAttributes().put(Attributes.Name.CLASS_PATH, jarFile.getName()); |
| |
| Closer closer = Closer.create(); |
| try { |
| FileOutputStream fileOut = closer.register(new FileOutputStream(jarFile)); |
| JarOutputStream jarOut = closer.register(new JarOutputStream(fileOut)); |
| for (String entry : entries) { |
| jarOut.putNextEntry(new ZipEntry(entry)); |
| Resources.copy(ClassPathTest.class.getResource(entry), jarOut); |
| jarOut.closeEntry(); |
| } |
| } catch (Throwable e) { |
| throw closer.rethrow(e); |
| } finally { |
| closer.close(); |
| } |
| } |
| |
| private static Manifest manifest(String content) throws IOException { |
| InputStream in = new ByteArrayInputStream(content.getBytes(US_ASCII)); |
| Manifest manifest = new Manifest(); |
| manifest.read(in); |
| return manifest; |
| } |
| |
| private static File fullpath(String path) { |
| return new File(new File(path).toURI()); |
| } |
| |
| private static class ResourceScanner extends ClassPath.Scanner { |
| final Set<String> resources = new HashSet<>(); |
| |
| @Override |
| protected void scanDirectory(ClassLoader loader, File root) throws IOException { |
| URI base = root.toURI(); |
| for (File entry : Files.fileTraverser().depthFirstPreOrder(root)) { |
| String resourceName = new File(base.relativize(entry.toURI()).getPath()).getPath(); |
| resources.add(resourceName); |
| } |
| } |
| |
| @Override |
| protected void scanJarFile(ClassLoader loader, JarFile file) throws IOException { |
| Enumeration<JarEntry> entries = file.entries(); |
| while (entries.hasMoreElements()) { |
| resources.add(entries.nextElement().getName()); |
| } |
| } |
| } |
| |
| private static URL makeJarUrlWithName(String name) throws IOException { |
| File fullPath = new File(Files.createTempDir(), name); |
| File jarFile = JarFileFinder.pickAnyJarFile(); |
| Files.copy(jarFile, fullPath); |
| return fullPath.toURI().toURL(); |
| } |
| |
| private static final class JarFileFinder extends ClassPath.Scanner { |
| |
| private File found; |
| |
| static File pickAnyJarFile() throws IOException { |
| JarFileFinder finder = new JarFileFinder(); |
| try { |
| finder.scan(JarFileFinder.class.getClassLoader()); |
| throw new IllegalStateException("No jar file found!"); |
| } catch (StopScanningException expected) { |
| return finder.found; |
| } |
| } |
| |
| @Override |
| protected void scanJarFile(ClassLoader loader, JarFile file) throws IOException { |
| this.found = new File(file.getName()); |
| throw new StopScanningException(); |
| } |
| |
| @Override |
| protected void scanDirectory(ClassLoader loader, File root) {} |
| |
| // Special exception just to terminate the scanning when we get any jar file to use. |
| private static final class StopScanningException extends RuntimeException {} |
| } |
| } |