/*******************************************************************************
* 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.Serializable;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.URL;
import java.util.EventListener;
import java.util.RandomAccess;
import java.util.concurrent.Callable;
import javax.enterprise.inject.Typed;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Qualifier;
import org.eclipse.sisu.BeanEntry;
import org.eclipse.sisu.EagerSingleton;
import org.eclipse.sisu.Mediator;
import org.eclipse.sisu.inject.BeanLocator;
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.name.Names;
import junit.framework.TestCase;
public class QualifiedTypesTest
extends TestCase
{
@Named
static class DefaultB01
{
}
@Named( "default" )
static class B01
extends Thread
{
}
@Named
@Typed
static class DefaultB02
implements RandomAccess, EventListener
{
}
@Named
@Typed( EventListener.class )
static class B02
implements RandomAccess, EventListener
{
}
@Named
static class B03
implements EventListener
{
}
@Named
@EagerSingleton
static class DefaultB03
{
static boolean initialized;
@Inject
void initialize()
{
initialized = true;
}
}
@Named( "TEST" )
static class DefaultB04
{
}
@Named( "TEST" )
static class B04
{
}
@Named
static class B05EventListener
implements Callable<String>, EventListener, Serializable
{
private static final long serialVersionUID = 1L;
public String call()
{
return "GO";
}
}
@Named
@Typed( { EventListener.class, Callable.class } )
static class B06
implements Callable<String>, EventListener, Serializable
{
private static final long serialVersionUID = 1L;
public String call()
{
return "GO";
}
}
static abstract class AbstractB01
{
}
@Typed( { AbstractB02.class, EventListener.class } )
static abstract class AbstractB02
implements RandomAccess, EventListener
{
}
static abstract class AbstractB03
implements EventListener
{
}
@Named
static class SubclassB00
extends B01
{
}
@Named
static class SubclassB01
extends AbstractB01
{
}
@Named
static class SubclassB02
extends AbstractB02
{
}
@Named
static class SubclassB03EventListener
extends AbstractB03
{
}
@Named( "RENAME" )
static class SubclassB04EventListener
extends AbstractB03
{
}
@Named
@org.eclipse.sisu.Typed( B02.class )
static class SubclassB06
extends B02
{
}
@Named
@Typed( Serializable.class )
static class SubclassB07
extends SubclassB06
implements Callable<String>, Serializable
{
private static final long serialVersionUID = 1L;
public String call()
{
return "GO";
}
}
@Named
@Typed
static class SubclassB08
extends B02
implements Serializable
{
private static final long serialVersionUID = 1L;
}
@Qualifier
@Retention( RetentionPolicy.RUNTIME )
public @interface Legacy
{
}
static class LegacyImpl
implements Legacy
{
public Class<? extends Annotation> annotationType()
{
return Legacy.class;
}
}
@Legacy
static class LegacyCallable
implements Callable<String>
{
public String call()
{
return "GO";
}
}
private BeanLocator locator;
private Injector injector;
@Override
protected void setUp()
throws Exception
{
final ClassSpace space =
new URLClassSpace( getClass().getClassLoader(), new URL[] { getClass().getResource( "" ) } );
injector = Guice.createInjector( new SpaceModule( space ) );
locator = injector.getInstance( BeanLocator.class );
assertTrue( DefaultB03.initialized );
}
private void checkDefaultBinding( final Class<?> api, final Class<?> imp )
{
final Annotation defaultName = Names.named( "default" );
assertSame( imp, locator.locate( Key.get( api ) ).iterator().next().getImplementationClass() );
assertSame( imp, locator.locate( Key.get( api, Named.class ) ).iterator().next().getImplementationClass() );
assertSame( imp, locator.locate( Key.get( api, defaultName ) ).iterator().next().getImplementationClass() );
}
private void checkNamedBinding( final Class<?> api, final String name, final Class<?> imp )
{
assertSame( imp,
locator.locate( Key.get( api, Names.named( name ) ) ).iterator().next().getImplementationClass() );
}
private void checkLegacyBinding( final Class<?> api, final Class<?> imp )
{
assertSame( imp, locator.locate( Key.get( api, Legacy.class ) ).iterator().next().getImplementationClass() );
}
public void testQualifiedBindings()
{
checkDefaultBinding( DefaultB01.class, DefaultB01.class );
checkDefaultBinding( DefaultB02.class, DefaultB02.class );
checkDefaultBinding( DefaultB03.class, DefaultB03.class );
checkDefaultBinding( DefaultB04.class, DefaultB04.class );
checkDefaultBinding( Thread.class, B01.class );
checkDefaultBinding( B04.class, B04.class );
checkNamedBinding( EventListener.class, B02.class.getName(), B02.class );
checkNamedBinding( EventListener.class, B03.class.getName(), B03.class );
checkNamedBinding( EventListener.class, B05EventListener.class.getName(), B05EventListener.class );
checkNamedBinding( EventListener.class, B06.class.getName(), B06.class );
checkNamedBinding( B01.class, SubclassB00.class.getName(), SubclassB00.class );
checkNamedBinding( AbstractB01.class, SubclassB01.class.getName(), SubclassB01.class );
checkNamedBinding( AbstractB02.class, SubclassB02.class.getName(), SubclassB02.class );
checkNamedBinding( EventListener.class, SubclassB03EventListener.class.getName(),
SubclassB03EventListener.class );
checkNamedBinding( EventListener.class, "RENAME", SubclassB04EventListener.class );
checkNamedBinding( B02.class, SubclassB06.class.getName(), SubclassB06.class );
checkNamedBinding( Serializable.class, SubclassB07.class.getName(), SubclassB07.class );
checkNamedBinding( Serializable.class, SubclassB08.class.getName(), SubclassB08.class );
checkLegacyBinding( Callable.class, LegacyCallable.class );
}
@ImplementedBy( AImpl.class )
interface A
{
}
static class AImpl
implements A
{
}
static class Ambiguous
implements Serializable, EventListener
{
private static final long serialVersionUID = 1L;
}
@SuppressWarnings( "rawtypes" )
static class RawMediator
implements Mediator
{
public void add( final BeanEntry bean, final Object watcher )
throws Exception
{
}
public void remove( final BeanEntry bean, final Object watcher )
throws Exception
{
}
}
abstract class AbstractNamedMediator
implements Mediator<Named, Object, Object>
{
}
static class BadBindings
implements Module
{
public void configure( final Binder binder )
{
final QualifiedTypeListener listener = new QualifiedTypeBinder( binder );
listener.hear( Ambiguous.class, null );
listener.hear( RawMediator.class, null );
listener.hear( AbstractNamedMediator.class, null );
listener.hear( AbstractModule.class, null );
}
}
public void testBadBindings()
{
try
{
Guice.createInjector( new BadBindings() );
}
catch ( final Exception e )
{
e.printStackTrace();
}
}
}