/**
* Copyright (c) 2008-2011 Sonatype, Inc.
* All rights reserved. Includes the third-party code listed at http://www.sonatype.com/products/nexus/attributions.
*
* This program is free software: you can redistribute it and/or modify it only under the terms of the GNU Affero General
* Public License Version 3 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License Version 3
* for more details.
*
* You should have received a copy of the GNU Affero General Public License Version 3 along with this program. If not, see
* http://www.gnu.org/licenses.
*
* Sonatype Nexus (TM) Open Source Version is available from Sonatype, Inc. Sonatype and Sonatype Nexus are trademarks of
* Sonatype, Inc. Apache Maven is a trademark of the Apache Foundation. M2Eclipse is a trademark of the Eclipse Foundation.
* All other trademarks are the property of their respective owners.
*/
package org.sonatype.guice.nexus.scanners;
import java.io.File;
import java.lang.annotation.Annotation;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Named;
import javax.inject.Singleton;
import junit.framework.TestCase;
import org.codehaus.plexus.component.annotations.Component;
import org.sonatype.guice.bean.reflect.ClassSpace;
import org.sonatype.guice.bean.reflect.DeferredClass;
import org.sonatype.guice.bean.reflect.URLClassSpace;
import org.sonatype.guice.bean.scanners.ClassSpaceScanner;
import org.sonatype.guice.plexus.annotations.ComponentImpl;
import org.sonatype.guice.plexus.config.Hints;
import org.sonatype.nexus.plugins.RepositoryType;
import org.sonatype.plugin.ExtensionPoint;
import org.sonatype.plugin.Managed;
public class NexusTypeVisitorTest
extends TestCase
{
interface BadInterface
{
}
@Deprecated
interface HostInterface0
{
}
@Singleton
interface UserInterface0
{
}
@ExtensionPoint
interface HostInterface1
{
}
interface SubHostInterface1
extends HostInterface1
{
}
@Managed
interface UserInterface1
{
}
interface SubUserInterface1
extends UserInterface1
{
}
@Singleton
@ExtensionPoint
interface HostInterface2
{
}
@Managed
@Singleton
interface UserInterface2
{
}
@Component( role = HostInterface0.class )
static class BeanA
implements HostInterface0
{
}
static class BeanB
implements HostInterface1
{
}
static class BeanC
implements HostInterface2
{
}
@Component( role = UserInterface0.class, instantiationStrategy = "per-lookup" )
static class BeanD
implements UserInterface0
{
}
static class BeanE
implements UserInterface1
{
}
static class BeanF
implements UserInterface2
{
}
@Named( "BeanA" )
static class NamedBeanA
implements HostInterface1
{
}
@Named( "" )
static class NamedBeanB
implements HostInterface2
{
}
@Named( "BeanC" )
static class NamedBeanC
implements UserInterface1
{
}
@Named( "" )
static class NamedBeanD
implements UserInterface2
{
}
@SuppressWarnings( "unused" )
@Component( role = SubHostInterface1.class )
static class ComponentBeanA
implements HostInterface1, SubHostInterface1
{
}
@SuppressWarnings( "unused" )
@Component( role = SubUserInterface1.class )
static class ComponentBeanB
implements UserInterface1, SubUserInterface1
{
}
static class BadBean
implements BadInterface
{
}
static class TestListener
implements NexusTypeListener
{
final Map<Component, DeferredClass<?>> components;
public TestListener( final Map<Component, DeferredClass<?>> components )
{
this.components = components;
}
public void hear( final String clazz )
{
}
public void hear( final RepositoryType repositoryType )
{
}
public void hear( final Component component, final DeferredClass<?> implementation, final Object source )
{
components.put( component, implementation );
}
public void hear( final Annotation qualifier, final Class<?> qualifiedType, final Object source )
{
}
}
public void testNexusTypeScanning()
throws MalformedURLException
{
final URL[] testURLs = new URL[] { new File( "target/test-classes" ).toURI().toURL() };
final ClassSpace space = new URLClassSpace( getClass().getClassLoader(), testURLs );
final Map<Component, DeferredClass<?>> components = new HashMap<Component, DeferredClass<?>>();
new ClassSpaceScanner( space ).accept( new NexusTypeVisitor( new TestListener( components ) ) );
assertEquals( 11, components.size() );
// non-extension so no automatic hinting...
assertEquals( BeanA.class,
components.get( new ComponentImpl( HostInterface0.class, Hints.DEFAULT_HINT, "singleton", "" ) ).load() );
assertEquals( BeanB.class,
components.get( new ComponentImpl( HostInterface1.class, BeanB.class.getName(), "per-lookup", "" ) ).load() );
assertEquals( BeanC.class,
components.get( new ComponentImpl( HostInterface2.class, BeanC.class.getName(), "singleton", "" ) ).load() );
// non-component so API @Singleton ignored...
assertEquals( BeanD.class,
components.get( new ComponentImpl( UserInterface0.class, Hints.DEFAULT_HINT, "per-lookup", "" ) ).load() );
assertEquals( BeanE.class,
components.get( new ComponentImpl( UserInterface1.class, Hints.DEFAULT_HINT, "per-lookup", "" ) ).load() );
final Class<?> duplicate =
components.get( new ComponentImpl( UserInterface2.class, Hints.DEFAULT_HINT, "singleton", "" ) ).load();
// duplicate binding, first-one wins... result may vary on different machines/OS's
assertTrue( duplicate.equals( BeanF.class ) || duplicate.equals( NamedBeanD.class ) );
assertEquals( NamedBeanA.class,
components.get( new ComponentImpl( HostInterface1.class, "BeanA", "per-lookup", "" ) ).load() );
assertEquals( NamedBeanB.class,
components.get( new ComponentImpl( HostInterface2.class, Hints.DEFAULT_HINT, "singleton", "" ) ).load() );
assertEquals( NamedBeanC.class,
components.get( new ComponentImpl( UserInterface1.class, "BeanC", "per-lookup", "" ) ).load() );
assertEquals( ComponentBeanA.class,
components.get( new ComponentImpl( SubHostInterface1.class, ComponentBeanA.class.getName(),
"per-lookup", "" ) ).load() );
assertEquals( ComponentBeanB.class,
components.get( new ComponentImpl( SubUserInterface1.class, Hints.DEFAULT_HINT, "per-lookup", "" ) ).load() );
}
}