| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 org.apache.commons.vfs2.impl; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.URL; |
| import java.net.URLConnection; |
| import java.util.Collections; |
| import java.util.Enumeration; |
| |
| import org.apache.commons.vfs2.AbstractProviderTestCase; |
| import org.apache.commons.vfs2.AbstractVfsTestCase; |
| import org.apache.commons.vfs2.Capability; |
| import org.apache.commons.vfs2.FileObject; |
| import org.apache.commons.vfs2.FileSystemException; |
| import org.apache.commons.vfs2.FileSystemManager; |
| import org.apache.commons.vfs2.FileType; |
| import org.junit.Test; |
| |
| /** |
| * VfsClassLoader test cases. |
| */ |
| public class VfsClassLoaderTests extends AbstractProviderTestCase { |
| |
| /** |
| * Returns the capabilities required by the tests of this test case. |
| */ |
| @Override |
| protected Capability[] getRequiredCapabilities() { |
| return new Capability[] { Capability.READ_CONTENT, Capability.URI }; |
| } |
| |
| /** |
| * Creates the classloader to use when testing. |
| */ |
| private VFSClassLoader createClassLoader() throws FileSystemException { |
| return new VFSClassLoader(getBaseFolder(), getManager()); |
| } |
| |
| /** |
| * Tests loading a class. |
| */ |
| @Test |
| public void testLoadClass() throws Exception { |
| final VFSClassLoader loader = createClassLoader(); |
| |
| final Class<?> testClass = loader.loadClass("code.ClassToLoad"); |
| final Package pack = testClass.getPackage(); |
| assertEquals("code", pack.getName()); |
| verifyPackage(pack, false); |
| |
| final Object testObject = testClass.newInstance(); |
| assertEquals("**PRIVATE**", testObject.toString()); |
| } |
| |
| /** |
| * Tests loading a resource. |
| */ |
| @Test |
| public void testLoadResource() throws Exception { |
| final VFSClassLoader loader = createClassLoader(); |
| |
| final URL resource = loader.getResource("read-tests/file1.txt"); |
| |
| assertNotNull(resource); |
| final URLConnection urlCon = resource.openConnection(); |
| assertSameURLContent(FILE1_CONTENT, urlCon); |
| } |
| |
| /** |
| * Tests package sealing. |
| */ |
| @Test |
| public void testSealing() throws Exception { |
| final VFSClassLoader loader = createClassLoader(); |
| final Class<?> testClass = loader.loadClass("code.sealed.AnotherClass"); |
| final Package pack = testClass.getPackage(); |
| assertEquals("code.sealed", pack.getName()); |
| verifyPackage(pack, true); |
| } |
| |
| /** |
| * Tests retrieving resources (from JAR searchpath). |
| * <p> |
| * This is run for all providers, but only when a local provider is present and jar extension is registered it will |
| * actually carry out all tests. |
| * </p> |
| */ |
| @Test |
| public void testGetResourcesJARs() throws Exception { |
| final FileSystemManager manager = getManager(); |
| try { |
| // hasProvider("file") cannot be used as it triggers default provider URL |
| manager.toFileObject(new File(".")); |
| } catch (final FileSystemException e) { |
| System.out.println("VfsClassLoaderTests no local file provider, skipping."); |
| return; |
| } |
| |
| // build search path without using #getBaseFolder() |
| // because NestedJarTestCase redefines it |
| final File baseDir = AbstractVfsTestCase.getTestDirectoryFile(); |
| final FileObject nestedJar = manager.resolveFile(baseDir, "nested.jar"); |
| final FileObject testJar = manager.resolveFile(baseDir, "test.jar"); |
| |
| // test setup needs to know about .jar extension - i.e. NestedJarTestCase |
| if (!manager.canCreateFileSystem(nestedJar)) { |
| System.out.println("VfsClassLoaderTests no layered .jar provider, skipping."); |
| return; |
| } |
| |
| // verify test setup |
| assertSame("nested.jar is required for testing", nestedJar.getType(), FileType.FILE); |
| assertSame("test.jar is required for testing", testJar.getType(), FileType.FILE); |
| |
| // System class loader (null) might be unpredictable in regards |
| // to returning resources for META-INF/MANIFEST.MF (see VFS-500) |
| // so we use our own which is guaranteed to not return any hit |
| final ClassLoader mockClassloader = new MockClassloader(); |
| final FileObject[] search = new FileObject[] { nestedJar, testJar }; |
| final VFSClassLoader loader = new VFSClassLoader(search, getManager(), mockClassloader); |
| |
| final Enumeration<URL> urls = loader.getResources("META-INF/MANIFEST.MF"); |
| final URL url1 = urls.nextElement(); |
| final URL url2 = urls.nextElement(); |
| |
| assertTrue("First resource must refer to nested.jar but was " + url1, |
| url1.toString().endsWith("nested.jar!/META-INF/MANIFEST.MF")); |
| assertTrue("Second resource must refer to test.jar but was " + url2, |
| url2.toString().endsWith("test.jar!/META-INF/MANIFEST.MF")); |
| } |
| |
| /** |
| * Tests retrieving resources (from local directory with .jar extension). |
| * <p> |
| * This test is repeated with various provider configurations but works on local files, only. |
| * </p> |
| */ |
| @Test |
| public void testGetResourcesNoLayerLocal() throws Exception { |
| final FileSystemManager manager = getManager(); |
| try { |
| // hasProvider("file") cannot be used as it triggers default provider URL |
| manager.toFileObject(new File(".")); |
| } catch (final FileSystemException e) { |
| System.out.println("VfsClassLoaderTests no local file provider, skipping."); |
| return; |
| } |
| final File baseDir = AbstractVfsTestCase.getTestDirectoryFile(); |
| |
| // setup test folder |
| final FileObject dir = manager.resolveFile(baseDir, "read-tests/dir1/subdir4.jar"); |
| assertSame("subdir4.jar/ is required for testing " + dir, dir.getType(), FileType.FOLDER); |
| assertFalse(manager.canCreateFileSystem(dir)); |
| |
| // prepare classloader |
| final FileObject[] search = new FileObject[] { dir }; |
| final ClassLoader mockClassloader = new MockClassloader(); |
| final VFSClassLoader loader = new VFSClassLoader(search, getManager(), mockClassloader); |
| |
| // verify resource loading |
| final Enumeration<URL> urls = loader.getResources("file1.txt"); |
| final URL url1 = urls.nextElement(); |
| assertFalse("Only one hit expected", urls.hasMoreElements()); |
| assertTrue("not pointing to resource " + url1, url1.toString().endsWith("subdir4.jar/file1.txt")); |
| } |
| |
| /** |
| * Verify the package loaded with class loader. |
| */ |
| private void verifyPackage(final Package pack, final boolean sealed) { |
| if (getBaseFolder().getFileSystem().hasCapability(Capability.MANIFEST_ATTRIBUTES)) { |
| assertEquals("ImplTitle", pack.getImplementationTitle()); |
| assertEquals("ImplVendor", pack.getImplementationVendor()); |
| assertEquals("1.1", pack.getImplementationVersion()); |
| assertEquals("SpecTitle", pack.getSpecificationTitle()); |
| assertEquals("SpecVendor", pack.getSpecificationVendor()); |
| assertEquals("1.0", pack.getSpecificationVersion()); |
| assertEquals(sealed, pack.isSealed()); |
| } else { |
| assertNull(pack.getImplementationTitle()); |
| assertNull(pack.getImplementationVendor()); |
| assertNull(pack.getImplementationVersion()); |
| assertNull(pack.getSpecificationTitle()); |
| assertNull(pack.getSpecificationVendor()); |
| assertNull(pack.getSpecificationVersion()); |
| assertFalse(pack.isSealed()); |
| } |
| } |
| |
| /** |
| * Non-Delegating Class Loader. |
| */ |
| public static class MockClassloader extends ClassLoader { |
| MockClassloader() { |
| super(null); |
| } |
| |
| /** |
| * This method will not return any hit to VFSClassLoader#testGetResourcesJARs. |
| */ |
| @Override |
| public Enumeration<URL> getResources(final String name) throws IOException { |
| return Collections.enumeration(Collections.<URL>emptyList()); |
| } |
| |
| @Override |
| protected Class<?> findClass(final String name) throws ClassNotFoundException { |
| fail("Not intended to be used for class loading."); |
| return null; |
| } |
| } |
| } |