/*******************************************************************************
* 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.plexus;
import org.codehaus.plexus.component.annotations.Component;
import org.eclipse.sisu.inject.DeferredClass;
import org.eclipse.sisu.inject.Sources;
import org.eclipse.sisu.space.QualifiedTypeBinder;
import org.eclipse.sisu.space.QualifiedTypeListener;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.Scopes;
import com.google.inject.binder.ScopedBindingBuilder;
/**
* {@link PlexusTypeListener} that binds Plexus {@link Component}s.
*/
public final class PlexusTypeBinder
implements PlexusTypeListener
{
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
private final Binder binder;
private final QualifiedTypeListener qualifiedTypeBinder;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
public PlexusTypeBinder( final Binder binder )
{
this.binder = binder;
qualifiedTypeBinder = new QualifiedTypeBinder( binder );
}
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
public void hear( final Class<?> qualifiedType, final Object source )
{
qualifiedTypeBinder.hear( qualifiedType, source );
}
@SuppressWarnings( { "unchecked", "rawtypes" } )
public void hear( final Component component, final DeferredClass<?> clazz, final Object source )
{
final Key roleKey = Roles.componentKey( component );
final String strategy = component.instantiationStrategy();
final Class<?> role = component.role();
final ScopedBindingBuilder sbb;
final Binder componentBinder = componentBinder( source, component.description() );
// special case when role is the implementation
if ( role.getName().equals( clazz.getName() ) )
{
if ( roleKey.getAnnotation() != null )
{
sbb = componentBinder.bind( roleKey ).to( role );
}
else
{
sbb = componentBinder.bind( roleKey );
}
}
else if ( Strategies.LOAD_ON_START.equals( strategy ) )
{
sbb = componentBinder.bind( roleKey ).to( clazz.load() ); // no need to defer
}
else
{
sbb = componentBinder.bind( roleKey ).toProvider( clazz.asProvider() );
}
if ( Strategies.LOAD_ON_START.equals( strategy ) )
{
sbb.asEagerSingleton();
}
else if ( !Strategies.PER_LOOKUP.equals( strategy ) )
{
sbb.in( Scopes.SINGLETON );
}
}
// ----------------------------------------------------------------------
// Implementation methods
// ----------------------------------------------------------------------
private Binder componentBinder( final Object source, final String description )
{
if ( null != description && description.length() > 0 )
{
return binder.withSource( Sources.describe( source, description ) );
}
return binder.withSource( source );
}
}