| /******************************************************************************* |
| * Copyright (c) 2010-present Sonatype, Inc. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Stuart McCulloch (Sonatype, Inc.) - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.sisu.space; |
| |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.net.URLClassLoader; |
| import java.net.URLStreamHandler; |
| import java.net.URLStreamHandlerFactory; |
| import java.util.Arrays; |
| import java.util.Enumeration; |
| import java.util.jar.Manifest; |
| |
| import org.eclipse.sisu.inject.DeferredClass; |
| import org.eclipse.sisu.space.oops.Handler; |
| import org.junit.Ignore; |
| |
| import junit.framework.TestCase; |
| |
| @Ignore( "Need to replace some test archives" ) |
| public class URLClassSpaceTest |
| extends TestCase |
| { |
| private static final URL SIMPLE_JAR = URLClassSpaceTest.class.getResource( "simple.jar" ); |
| |
| private static final URL CLASS_PATH_JAR = URLClassSpaceTest.class.getResource( "class path.jar" ); |
| |
| private static final URL COMMONS_LOGGING_JAR = URLClassSpaceTest.class.getResource( "commons-logging-1.1.1.jar" ); |
| |
| private static final URL CORRUPT_MANIFEST = URLClassSpaceTest.class.getResource( "corrupt.manifest/" ); |
| |
| private static final URL BROKEN_JAR = URLClassSpaceTest.class.getResource( "broken.jar" ); |
| |
| private static final URL NESTED_WAR = URLClassSpaceTest.class.getResource( "nested.war" ); |
| |
| public void testHashCodeAndEquals() |
| { |
| final ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); |
| final ClassSpace space = new URLClassSpace( systemLoader, null ); |
| |
| assertEquals( space, space ); |
| |
| assertEquals( space, new URLClassSpace( systemLoader, new URL[] { SIMPLE_JAR } ) ); |
| |
| assertFalse( space.equals( new ClassSpace() |
| { |
| public Class<?> loadClass( final String name ) |
| { |
| return space.loadClass( name ); |
| } |
| |
| public DeferredClass<?> deferLoadClass( final String name ) |
| { |
| return space.deferLoadClass( name ); |
| } |
| |
| public Enumeration<URL> getResources( final String name ) |
| { |
| return space.getResources( name ); |
| } |
| |
| public URL getResource( final String name ) |
| { |
| return space.getResource( name ); |
| } |
| |
| public Enumeration<URL> findEntries( final String path, final String glob, final boolean recurse ) |
| { |
| return space.findEntries( path, glob, recurse ); |
| } |
| } ) ); |
| |
| assertEquals( systemLoader.hashCode(), space.hashCode() ); |
| assertEquals( systemLoader.toString(), space.toString() ); |
| } |
| |
| public void testClassSpaceResources() |
| throws IOException |
| { |
| final ClassSpace space = new URLClassSpace( URLClassLoader.newInstance( new URL[] { COMMONS_LOGGING_JAR } ) ); |
| Enumeration<URL> e; |
| |
| int n = 0; |
| e = space.getResources( "META-INF/MANIFEST.MF" ); |
| while ( true ) |
| { |
| n++; |
| |
| // should have several matches from parent loader, local match should be last |
| if ( e.nextElement().getPath().startsWith( COMMONS_LOGGING_JAR.toString() ) ) |
| { |
| assertFalse( e.hasMoreElements() ); |
| break; |
| } |
| } |
| assertTrue( n > 1 ); |
| |
| e = space.findEntries( "META-INF", "*.MF", false ); |
| |
| // only expect to see single result |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( COMMONS_LOGGING_JAR.toString() ) ); |
| assertFalse( e.hasMoreElements() ); |
| |
| final URL manifestURL = space.getResource( "META-INF/MANIFEST.MF" ); |
| assertNotNull( manifestURL ); |
| new Manifest( manifestURL.openStream() ); |
| } |
| |
| public void testClassPathExpansion() |
| throws IOException |
| { |
| // System.setProperty( "java.protocol.handler.pkgs", getClass().getPackage().getName() ); |
| URL.setURLStreamHandlerFactory( new URLStreamHandlerFactory() |
| { |
| public URLStreamHandler createURLStreamHandler( final String protocol ) |
| { |
| if ( "oops".equals( protocol ) ) |
| { |
| return new Handler(); |
| } |
| return null; |
| } |
| } ); |
| |
| final URLClassSpace space = new URLClassSpace( URLClassLoader.newInstance( new URL[] { SIMPLE_JAR, |
| CLASS_PATH_JAR, null, new URL( "oops:bad/" ), CLASS_PATH_JAR, CORRUPT_MANIFEST } ) ); |
| |
| final Enumeration<URL> e = space.findEntries( "META-INF", "*.MF", false ); |
| |
| // expect to see three results |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( SIMPLE_JAR.toString() ) ); |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( CLASS_PATH_JAR.toString() ) ); |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( COMMONS_LOGGING_JAR.toString() ) ); |
| assertFalse( e.hasMoreElements() ); |
| |
| assertTrue( Arrays.equals( new URL[] { SIMPLE_JAR, CLASS_PATH_JAR, new URL( "oops:bad/" ), CORRUPT_MANIFEST, |
| BROKEN_JAR, COMMONS_LOGGING_JAR }, space.getURLs() ) ); |
| } |
| |
| public void testNullSearchPath() |
| { |
| final ClassSpace space = new URLClassSpace( getClass().getClassLoader(), null ); |
| final Enumeration<URL> e = space.findEntries( null, null, true ); |
| |
| // local search should see nothing |
| assertFalse( e.hasMoreElements() ); |
| } |
| |
| public void testEmptySearchPath() |
| { |
| final ClassSpace space = new URLClassSpace( getClass().getClassLoader(), new URL[0] ); |
| final Enumeration<URL> e = space.findEntries( null, null, true ); |
| |
| // local search should see nothing |
| assertFalse( e.hasMoreElements() ); |
| } |
| |
| public void testBrokenResources() |
| { |
| final ClassSpace space = new URLClassSpace( new ClassLoader() |
| { |
| @Override |
| public Enumeration<URL> getResources( final String name ) |
| throws IOException |
| { |
| throw new IOException(); |
| } |
| } ); |
| |
| // should see nothing, and not throw any exceptions |
| assertFalse( space.getResources( "error" ).hasMoreElements() ); |
| } |
| |
| public void testClassPathDetection() |
| { |
| final ClassLoader parent = URLClassLoader.newInstance( new URL[] { CLASS_PATH_JAR } ); |
| final ClassLoader child = URLClassLoader.newInstance( new URL[0], parent ); |
| final ClassLoader grandchild = new URLClassLoader( new URL[0], child ) |
| { |
| @Override |
| public URL[] getURLs() |
| { |
| return null; |
| } |
| }; |
| |
| final Enumeration<URL> e = new URLClassSpace( new ClassLoader( grandchild ) |
| { |
| } ).findEntries( "META-INF", "*.MF", false ); |
| |
| // expect to see three results |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( CLASS_PATH_JAR.toString() ) ); |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( COMMONS_LOGGING_JAR.toString() ) ); |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( SIMPLE_JAR.toString() ) ); |
| assertFalse( e.hasMoreElements() ); |
| |
| final ClassLoader orphan = URLClassLoader.newInstance( new URL[0], null ); |
| |
| // expect to see no results |
| assertFalse( new URLClassSpace( orphan ).findEntries( "META-INF", "*.MF", false ).hasMoreElements() ); |
| } |
| |
| public void testJarProtocol() |
| throws MalformedURLException |
| { |
| final URLClassSpace space = |
| new URLClassSpace( URLClassLoader.newInstance( new URL[] { new URL( "jar:" + CLASS_PATH_JAR + "!/" ) } ) ); |
| |
| final Enumeration<URL> e = space.findEntries( "META-INF", "*.MF", false ); |
| |
| // expect to see three results |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( CLASS_PATH_JAR.toString() ) ); |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( COMMONS_LOGGING_JAR.toString() ) ); |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().getPath().startsWith( SIMPLE_JAR.toString() ) ); |
| assertFalse( e.hasMoreElements() ); |
| } |
| |
| public void testNestedWar() |
| throws MalformedURLException |
| { |
| final URLClassSpace space = new URLClassSpace( URLClassLoader.newInstance( new URL[] { |
| new URL( "jar:" + NESTED_WAR + "!/WEB-INF/classes/" ), |
| new URL( "jar:" + NESTED_WAR + "!/WEB-INF/lib/commons-logging-1.1.1.jar" ) } ) ); |
| |
| Enumeration<URL> e = space.findEntries( "META-INF", "*.MF", false ); |
| |
| // expect to see one result |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().toString().endsWith( "/nested.war!/WEB-INF/lib/commons-logging-1.1.1.jar#META-INF/MANIFEST.MF" ) ); |
| assertFalse( e.hasMoreElements() ); |
| |
| e = space.findEntries( null, "Log.class", true ); |
| |
| // only one result, as can't "glob" embedded directory |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().toString().endsWith( "/nested.war!/WEB-INF/lib/commons-logging-1.1.1.jar#org/apache/commons/logging/Log.class" ) ); |
| assertFalse( e.hasMoreElements() ); |
| |
| e = space.findEntries( "org/apache/commons/logging", "Log.class", false ); |
| |
| // can see both results, as using non-"globbed" search |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().toString().endsWith( "/nested.war!/WEB-INF/classes/org/apache/commons/logging/Log.class" ) ); |
| assertTrue( e.hasMoreElements() ); |
| assertTrue( e.nextElement().toString().endsWith( "/nested.war!/WEB-INF/lib/commons-logging-1.1.1.jar#org/apache/commons/logging/Log.class" ) ); |
| assertFalse( e.hasMoreElements() ); |
| |
| e = space.findEntries( null, "missing", true ); |
| assertFalse( e.hasMoreElements() ); |
| } |
| } |