| /******************************************************************************* |
| * 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.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.net.URLClassLoader; |
| import java.net.URLStreamHandler; |
| import java.net.URLStreamHandlerFactory; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Enumeration; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import javax.inject.Named; |
| import javax.inject.Qualifier; |
| import javax.inject.Singleton; |
| |
| import org.eclipse.sisu.inject.DeferredClass; |
| import org.eclipse.sisu.space.oops.Handler; |
| import org.junit.Ignore; |
| |
| import junit.framework.TestCase; |
| |
| public class QualifiedScanningTest |
| extends TestCase |
| { |
| @Named |
| interface A |
| { |
| } |
| |
| @Named |
| static abstract class B |
| { |
| } |
| |
| @Named |
| static class C |
| { |
| } |
| |
| @Qualifier |
| @Retention( RetentionPolicy.RUNTIME ) |
| public @interface Legacy |
| { |
| } |
| |
| @Named |
| @Legacy |
| static class D |
| { |
| } |
| |
| @Legacy |
| @Named |
| static class E |
| { |
| } |
| |
| static class F |
| extends B |
| { |
| } |
| |
| @Singleton |
| static class G |
| { |
| } |
| |
| static class TestListener |
| implements QualifiedTypeListener |
| { |
| final List<Class<?>> clazzes = new ArrayList<Class<?>>(); |
| |
| final Set<Object> sources = new HashSet<Object>(); |
| |
| public void hear( final Class<?> clazz, final Object source ) |
| { |
| clazzes.add( clazz ); |
| sources.add( source ); |
| } |
| } |
| |
| public void testQualifiedScanning() |
| { |
| final TestListener listener = new TestListener(); |
| final ClassSpace space = |
| new URLClassSpace( getClass().getClassLoader(), new URL[] { getClass().getResource( "" ) } ); |
| new SpaceScanner( space ).accept( new QualifiedTypeVisitor( listener ) ); |
| assertEquals( 37, listener.clazzes.size() ); |
| |
| assertTrue( listener.clazzes.contains( C.class ) ); |
| assertTrue( listener.clazzes.contains( D.class ) ); |
| assertTrue( listener.clazzes.contains( E.class ) ); |
| } |
| |
| public void testAdaptedScanning() |
| { |
| final TestListener listener = new TestListener(); |
| final ClassSpace space = |
| new URLClassSpace( getClass().getClassLoader(), new URL[] { getClass().getResource( "" ) } ); |
| final SpaceVisitor visitor = new QualifiedTypeVisitor( listener ); |
| new SpaceScanner( space ).accept( new SpaceVisitor() |
| { |
| public void enterSpace( final ClassSpace _space ) |
| { |
| visitor.enterSpace( _space ); |
| } |
| |
| public ClassVisitor visitClass( final URL url ) |
| { |
| if ( url.toString().contains( "$D.class" ) ) |
| { |
| return null; |
| } |
| return visitor.visitClass( url ); |
| } |
| |
| public void leaveSpace() |
| { |
| visitor.leaveSpace(); |
| } |
| } ); |
| |
| assertEquals( 36, listener.clazzes.size() ); |
| |
| assertTrue( listener.clazzes.contains( C.class ) ); |
| assertTrue( listener.clazzes.contains( E.class ) ); |
| } |
| |
| public void testFilteredScanning() |
| { |
| final TestListener listener = new TestListener(); |
| final ClassSpace space = |
| new URLClassSpace( getClass().getClassLoader(), new URL[] { getClass().getResource( "" ) } ); |
| final SpaceVisitor visitor = new QualifiedTypeVisitor( listener ); |
| new SpaceScanner( space, new ClassFinder() |
| { |
| public Enumeration<URL> findClasses( final ClassSpace space2 ) |
| { |
| return space2.findEntries( null, "*D.class", true ); |
| } |
| } ).accept( visitor ); |
| |
| assertEquals( 1, listener.clazzes.size() ); |
| |
| assertTrue( listener.clazzes.contains( D.class ) ); |
| } |
| |
| @Ignore( "Need to replace some test archives" ) |
| public void /* test */ignoreIndexedScanning() |
| { |
| final TestListener listener = new TestListener(); |
| final ClassSpace space = |
| new URLClassSpace( getClass().getClassLoader(), new URL[] { getClass().getResource( "" ) } ); |
| final SpaceVisitor visitor = new QualifiedTypeVisitor( listener ); |
| new SpaceScanner( space, SpaceModule.LOCAL_INDEX ).accept( visitor ); |
| |
| // we deliberately use a partial index |
| |
| assertEquals( 2, listener.clazzes.size() ); |
| |
| assertTrue( listener.clazzes.contains( C.class ) ); |
| assertTrue( listener.clazzes.contains( D.class ) ); |
| } |
| |
| public void testBrokenScanning() |
| 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 ClassSpace space = |
| new URLClassSpace( getClass().getClassLoader(), new URL[] { getClass().getResource( "" ) } ); |
| |
| final URL badURL = new URL( "oops:bad/" ); |
| final ClassSpace brokenResourceSpace = 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 badURL; |
| } |
| |
| public Enumeration<URL> findEntries( final String path, final String glob, final boolean recurse ) |
| { |
| return Collections.enumeration( Collections.singleton( badURL ) ); |
| } |
| }; |
| |
| new SpaceScanner( brokenResourceSpace ).accept( new QualifiedTypeVisitor( null ) ); |
| |
| final ClassSpace brokenLoadSpace = new ClassSpace() |
| { |
| public Class<?> loadClass( final String name ) |
| { |
| throw new TypeNotPresentException( name, new ClassNotFoundException( 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 ); |
| } |
| }; |
| |
| new SpaceScanner( brokenLoadSpace ).accept( new QualifiedTypeVisitor( null ) ); |
| |
| SpaceScanner.accept( null, null ); |
| |
| assertFalse( SpaceModule.LOCAL_INDEX.findClasses( brokenResourceSpace ).hasMoreElements() ); |
| } |
| |
| public void testSourceDetection() |
| throws MalformedURLException |
| { |
| final TestListener listener = new TestListener(); |
| |
| final QualifiedTypeVisitor visitor = new QualifiedTypeVisitor( listener ); |
| |
| visitor.enterSpace( new URLClassSpace( getClass().getClassLoader(), new URL[] { getClass().getResource( "" ) } ) ); |
| |
| assertEquals( 0, listener.sources.size() ); |
| |
| visitor.visitClass( new URL( "file:target/classes/java/lang/Object.class" ) ); |
| visitor.enterClass( 0, "java/lang/Object", null, null ); |
| visitor.visitAnnotation( "Ljavax/inject/Named;" ); |
| visitor.leaveClass(); |
| |
| assertEquals( 1, listener.sources.size() ); |
| assertTrue( listener.sources.contains( "target/classes/" ) ); |
| |
| visitor.visitClass( new URL( "jar:file:bar.jar!/java/lang/String.class" ) ); |
| visitor.enterClass( 0, "java/lang/String", null, null ); |
| visitor.visitAnnotation( "Ljavax/inject/Named;" ); |
| visitor.leaveClass(); |
| |
| assertEquals( 2, listener.sources.size() ); |
| assertTrue( listener.sources.contains( "target/classes/" ) ); |
| assertTrue( listener.sources.contains( "file:bar.jar!/" ) ); |
| |
| visitor.visitClass( new URL( "file:some/obfuscated/location" ) ); |
| visitor.enterClass( 0, "java/lang/Integer", null, null ); |
| visitor.visitAnnotation( "Ljavax/inject/Named;" ); |
| visitor.leaveClass(); |
| |
| assertEquals( 3, listener.sources.size() ); |
| assertTrue( listener.sources.contains( "target/classes/" ) ); |
| assertTrue( listener.sources.contains( "file:bar.jar!/" ) ); |
| assertTrue( listener.sources.contains( "some/obfuscated/location" ) ); |
| |
| visitor.leaveSpace(); |
| } |
| |
| public void testOptionalLogging() |
| throws Exception |
| { |
| final Level level = Logger.getLogger( "" ).getLevel(); |
| try |
| { |
| Logger.getLogger( "" ).setLevel( Level.SEVERE ); |
| |
| // check everything still works without any SLF4J jars |
| final ClassLoader noLoggingLoader = |
| new URLClassLoader( new URLClassSpace( getClass().getClassLoader() ).getURLs(), null ) |
| { |
| @Override |
| protected synchronized Class<?> loadClass( final String name, final boolean resolve ) |
| throws ClassNotFoundException |
| { |
| if ( name.contains( "slf4j" ) ) |
| { |
| throw new ClassNotFoundException( name ); |
| } |
| if ( name.contains( "cobertura" ) ) |
| { |
| return QualifiedScanningTest.class.getClassLoader().loadClass( name ); |
| } |
| return super.loadClass( name, resolve ); |
| } |
| }; |
| |
| noLoggingLoader.loadClass( BrokenScanningExample.class.getName() ).newInstance(); |
| } |
| finally |
| { |
| Logger.getLogger( "" ).setLevel( level ); |
| } |
| } |
| |
| public void testICU4J() |
| { |
| final ClassLoader loader = getClass().getClassLoader(); |
| final URL[] urls = { loader.getResource( "icu4j-2.6.1.jar" ) }; |
| final ClassSpace space = new URLClassSpace( loader, urls ); |
| |
| final TestListener listener = new TestListener(); |
| new SpaceScanner( space ).accept( new QualifiedTypeVisitor( listener ) ); |
| assertEquals( 0, listener.clazzes.size() ); |
| } |
| } |