blob: b63fb8343a8405c5c1ebbbb588ee9ef71a8200ee [file] [log] [blame]
/*******************************************************************************
* 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
*
* Minimal facade required to be binary-compatible with legacy Plexus API
*******************************************************************************/
package org.codehaus.plexus;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Provider;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextMapAdapter;
import org.codehaus.plexus.context.DefaultContext;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.LoggerManager;
import org.codehaus.plexus.logging.console.ConsoleLoggerManager;
import org.eclipse.sisu.bean.BeanManager;
import org.eclipse.sisu.bean.LifecycleManager;
import org.eclipse.sisu.inject.DefaultBeanLocator;
import org.eclipse.sisu.inject.DefaultRankingFunction;
import org.eclipse.sisu.inject.DeferredClass;
import org.eclipse.sisu.inject.DeferredProvider;
import org.eclipse.sisu.inject.InjectorBindings;
import org.eclipse.sisu.inject.MutableBeanLocator;
import org.eclipse.sisu.inject.RankingFunction;
import org.eclipse.sisu.plexus.ComponentDescriptorBeanModule;
import org.eclipse.sisu.plexus.DefaultPlexusBeanLocator;
import org.eclipse.sisu.plexus.Hints;
import org.eclipse.sisu.plexus.PlexusAnnotatedBeanModule;
import org.eclipse.sisu.plexus.PlexusBean;
import org.eclipse.sisu.plexus.PlexusBeanConverter;
import org.eclipse.sisu.plexus.PlexusBeanLocator;
import org.eclipse.sisu.plexus.PlexusBeanModule;
import org.eclipse.sisu.plexus.PlexusBindingModule;
import org.eclipse.sisu.plexus.PlexusDateTypeConverter;
import org.eclipse.sisu.plexus.PlexusLifecycleManager;
import org.eclipse.sisu.plexus.PlexusXmlBeanConverter;
import org.eclipse.sisu.plexus.PlexusXmlBeanModule;
import org.eclipse.sisu.plexus.RealmManager;
import org.eclipse.sisu.space.BeanScanning;
import org.eclipse.sisu.space.ClassSpace;
import org.eclipse.sisu.space.LoadedClass;
import org.eclipse.sisu.space.URLClassSpace;
import org.eclipse.sisu.wire.EntryListAdapter;
import org.eclipse.sisu.wire.EntryMapAdapter;
import org.eclipse.sisu.wire.MergedModule;
import org.eclipse.sisu.wire.ParameterKeys;
import org.eclipse.sisu.wire.WireModule;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
import com.google.inject.util.Providers;
/**
* {@link PlexusContainer} shim that delegates to a Plexus-aware Guice {@link Injector}.
*/
@SuppressWarnings( { "unchecked", "rawtypes" } )
public final class DefaultPlexusContainer
implements MutablePlexusContainer
{
// ----------------------------------------------------------------------
// Static initialization
// ----------------------------------------------------------------------
static
{
System.setProperty( "guice.disable.misplaced.annotation.check", "true" );
}
// ----------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------
private static final String DEFAULT_REALM_NAME = "plexus.core";
private static final Module[] NO_CUSTOM_MODULES = {};
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
final AtomicInteger plexusRank = new AtomicInteger();
final Map<ClassRealm, List<ComponentDescriptor<?>>> descriptorMap =
new IdentityHashMap<ClassRealm, List<ComponentDescriptor<?>>>();
final ThreadLocal<ClassRealm> lookupRealm = new ThreadLocal<ClassRealm>();
final LoggerManagerProvider loggerManagerProvider = new LoggerManagerProvider();
final MutableBeanLocator qualifiedBeanLocator = new DefaultBeanLocator();
final Context context;
final Map<?, ?> variables;
final ClassRealm containerRealm;
final RealmManager realmManager;
final PlexusBeanLocator plexusBeanLocator;
final BeanManager plexusBeanManager;
private final String componentVisibility;
private final boolean isAutoWiringEnabled;
private final BeanScanning scanning;
private final Module containerModule = new ContainerModule();
private final Module defaultsModule = new DefaultsModule();
private LoggerManager loggerManager = new ConsoleLoggerManager();
private Logger logger;
private boolean disposing;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
public DefaultPlexusContainer()
throws PlexusContainerException
{
this( new DefaultContainerConfiguration() );
}
public DefaultPlexusContainer( final ContainerConfiguration configuration )
throws PlexusContainerException
{
this( configuration, NO_CUSTOM_MODULES );
}
@SuppressWarnings( "finally" )
public DefaultPlexusContainer( final ContainerConfiguration configuration, final Module... customModules )
throws PlexusContainerException
{
final URL plexusXml = lookupPlexusXml( configuration );
context = getContextComponent( configuration );
context.put( PlexusConstants.PLEXUS_KEY, this );
variables = new ContextMapAdapter( context );
containerRealm = lookupContainerRealm( configuration );
realmManager = new RealmManager( qualifiedBeanLocator );
containerRealm.getWorld().addListener( realmManager );
componentVisibility = configuration.getComponentVisibility();
isAutoWiringEnabled = configuration.getAutoWiring();
scanning = parseScanningOption( configuration.getClassPathScanning() );
plexusBeanLocator = new DefaultPlexusBeanLocator( qualifiedBeanLocator, realmManager, componentVisibility );
final BeanManager jsr250Lifecycle = configuration.getJSR250Lifecycle() ? new LifecycleManager() : null;
plexusBeanManager = new PlexusLifecycleManager( Providers.of( context ), loggerManagerProvider, //
new SLF4JLoggerFactoryProvider(), jsr250Lifecycle );
setLookupRealm( containerRealm );
final List<PlexusBeanModule> beanModules = new ArrayList<PlexusBeanModule>();
final ClassSpace space = new URLClassSpace( containerRealm );
beanModules.add( new PlexusXmlBeanModule( space, variables, plexusXml ) );
final BeanScanning global = BeanScanning.INDEX == scanning ? BeanScanning.GLOBAL_INDEX : scanning;
beanModules.add( new PlexusAnnotatedBeanModule( space, variables, global ) );
try
{
addPlexusInjector( beanModules, new BootModule( customModules ) );
}
catch ( final RuntimeException e )
{
try
{
dispose(); // cleanup as much as possible
}
finally
{
throw e; // always report original failure
}
}
}
// ----------------------------------------------------------------------
// Context methods
// ----------------------------------------------------------------------
public Context getContext()
{
return context;
}
// ----------------------------------------------------------------------
// Lookup methods
// ----------------------------------------------------------------------
public Object lookup( final String role )
throws ComponentLookupException
{
return lookup( role, "" );
}
public Object lookup( final String role, final String hint )
throws ComponentLookupException
{
return lookup( null, role, hint );
}
public <T> T lookup( final Class<T> role )
throws ComponentLookupException
{
return lookup( role, "" );
}
public <T> T lookup( final Class<T> role, final String hint )
throws ComponentLookupException
{
return lookup( role, null, hint );
}
public <T> T lookup( final Class<T> type, final String role, final String hint )
throws ComponentLookupException
{
try
{
return locate( role, type, hint ).iterator().next().getValue();
}
catch ( final RuntimeException e )
{
throw new ComponentLookupException( e, null != type ? type.getName() : role, hint );
}
}
public List<Object> lookupList( final String role )
throws ComponentLookupException
{
return new EntryListAdapter<Object>( locate( role, null ) );
}
public <T> List<T> lookupList( final Class<T> role )
throws ComponentLookupException
{
return new EntryListAdapter<T>( locate( null, role ) );
}
public Map<String, Object> lookupMap( final String role )
throws ComponentLookupException
{
return new EntryMapAdapter<String, Object>( locate( role, null ) );
}
public <T> Map<String, T> lookupMap( final Class<T> role )
throws ComponentLookupException
{
return new EntryMapAdapter<String, T>( locate( null, role ) );
}
// ----------------------------------------------------------------------
// Query methods
// ----------------------------------------------------------------------
public boolean hasComponent( final String role )
{
return hasComponent( role, "" );
}
public boolean hasComponent( final String role, final String hint )
{
return hasComponent( null, role, hint );
}
public boolean hasComponent( final Class role )
{
return hasComponent( role, "" );
}
public boolean hasComponent( final Class role, final String hint )
{
return hasComponent( role, null, hint );
}
public boolean hasComponent( final Class type, final String role, final String hint )
{
return hasPlexusBeans( locate( role, type, hint ) );
}
// ----------------------------------------------------------------------
// Component descriptor methods
// ----------------------------------------------------------------------
public void addComponent( final Object component, final String role )
{
try
{
addComponent( component, component.getClass().getClassLoader().loadClass( role ), Hints.DEFAULT_HINT );
}
catch ( final ClassNotFoundException e )
{
throw new TypeNotPresentException( role, e );
}
}
public <T> void addComponent( final T component, final Class<?> role, final String hint )
{
// this is only used in Maven3 tests, so keep it simple...
qualifiedBeanLocator.add( new InjectorBindings( Guice.createInjector( new Module()
{
public void configure( final Binder binder )
{
if ( Hints.isDefaultHint( hint ) )
{
binder.bind( (Class) role ).toInstance( component );
}
else
{
binder.bind( (Class) role ).annotatedWith( Names.named( hint ) ).toInstance( component );
}
}
} ), new DefaultRankingFunction( plexusRank.incrementAndGet() ) ) );
}
public <T> void addComponentDescriptor( final ComponentDescriptor<T> descriptor )
{
ClassRealm realm = descriptor.getRealm();
if ( null == realm )
{
realm = containerRealm;
descriptor.setRealm( realm );
}
synchronized ( descriptorMap )
{
List<ComponentDescriptor<?>> descriptors = descriptorMap.get( realm );
if ( null == descriptors )
{
descriptors = new ArrayList<ComponentDescriptor<?>>();
descriptorMap.put( realm, descriptors );
}
descriptors.add( descriptor );
}
if ( containerRealm == realm )
{
discoverComponents( containerRealm ); // for Maven3 testing
}
}
public ComponentDescriptor<?> getComponentDescriptor( final String role, final String hint )
{
return getComponentDescriptor( null, role, hint );
}
public <T> ComponentDescriptor<T> getComponentDescriptor( final Class<T> type, final String role,
final String hint )
{
final Iterator<PlexusBean<T>> i = locate( role, type, hint ).iterator();
if ( i.hasNext() )
{
final PlexusBean<T> bean = i.next();
if ( bean.getImplementationClass() != null )
{
return newComponentDescriptor( role, bean );
}
}
return null;
}
public List getComponentDescriptorList( final String role )
{
return getComponentDescriptorList( null, role );
}
public <T> List<ComponentDescriptor<T>> getComponentDescriptorList( final Class<T> type, final String role )
{
final List<ComponentDescriptor<T>> tempList = new ArrayList<ComponentDescriptor<T>>();
for ( final PlexusBean<T> bean : locate( role, type ) )
{
tempList.add( newComponentDescriptor( role, bean ) );
}
return tempList;
}
public Map getComponentDescriptorMap( final String role )
{
return getComponentDescriptorMap( null, role );
}
public <T> Map<String, ComponentDescriptor<T>> getComponentDescriptorMap( final Class<T> type, final String role )
{
final Map<String, ComponentDescriptor<T>> tempMap = new LinkedHashMap<String, ComponentDescriptor<T>>();
for ( final PlexusBean<T> bean : locate( role, type ) )
{
tempMap.put( bean.getKey(), newComponentDescriptor( role, bean ) );
}
return tempMap;
}
public List<ComponentDescriptor<?>> discoverComponents( final ClassRealm realm )
{
return discoverComponents( realm, NO_CUSTOM_MODULES );
}
public List<ComponentDescriptor<?>> discoverComponents( final ClassRealm realm, final Module... customModules )
{
try
{
final List<PlexusBeanModule> beanModules = new ArrayList<PlexusBeanModule>();
synchronized ( descriptorMap )
{
final ClassSpace space = new URLClassSpace( realm );
final List<ComponentDescriptor<?>> descriptors = descriptorMap.remove( realm );
if ( null != descriptors )
{
beanModules.add( new ComponentDescriptorBeanModule( space, descriptors ) );
}
if ( containerRealm != realm && !realmManager.isManaged( realm ) )
{
beanModules.add( new PlexusXmlBeanModule( space, variables ) );
final BeanScanning local = BeanScanning.GLOBAL_INDEX == scanning ? BeanScanning.INDEX : scanning;
beanModules.add( new PlexusAnnotatedBeanModule( space, variables, local ) );
}
}
if ( !beanModules.isEmpty() )
{
realmManager.manage( realm, addPlexusInjector( beanModules, customModules ) );
}
}
catch ( final RuntimeException e )
{
getLogger().warn( realm.toString(), e );
}
return null; // no-one actually seems to use or check the returned component list!
}
public Injector addPlexusInjector( final List<? extends PlexusBeanModule> beanModules,
final Module... customModules )
{
final List<Module> modules = new ArrayList<Module>();
modules.add( containerModule );
Collections.addAll( modules, customModules );
modules.add( new PlexusBindingModule( plexusBeanManager, beanModules ) );
modules.add( defaultsModule );
return Guice.createInjector( isAutoWiringEnabled ? new WireModule( modules ) : new MergedModule( modules ) );
}
// ----------------------------------------------------------------------
// Class realm methods
// ----------------------------------------------------------------------
public ClassWorld getClassWorld()
{
return containerRealm.getWorld();
}
public ClassRealm getContainerRealm()
{
return containerRealm;
}
public ClassRealm setLookupRealm( final ClassRealm realm )
{
final ClassRealm oldRealm = lookupRealm.get();
lookupRealm.set( realm );
return oldRealm;
}
public ClassRealm getLookupRealm()
{
return lookupRealm.get();
}
public ClassRealm createChildRealm( final String id )
{
try
{
return containerRealm.createChildRealm( id );
}
catch ( final DuplicateRealmException e1 )
{
try
{
return getClassWorld().getRealm( id );
}
catch ( final NoSuchRealmException e2 )
{
return null; // should never happen!
}
}
}
// ----------------------------------------------------------------------
// Logger methods
// ----------------------------------------------------------------------
public synchronized LoggerManager getLoggerManager()
{
return loggerManager;
}
@Inject( optional = true )
public synchronized void setLoggerManager( final LoggerManager loggerManager )
{
if ( null != loggerManager )
{
this.loggerManager = loggerManager;
}
else
{
this.loggerManager = new ConsoleLoggerManager();
}
logger = null; // refresh our local logger
}
public synchronized Logger getLogger()
{
if ( null == logger )
{
logger = loggerManager.getLoggerForComponent( PlexusContainer.class.getName(), null );
}
return logger;
}
// ----------------------------------------------------------------------
// Shutdown methods
// ----------------------------------------------------------------------
public void release( final Object component )
{
plexusBeanManager.unmanage( component );
}
public void releaseAll( final Map<String, ?> components )
{
for ( final Object o : components.values() )
{
release( o );
}
}
public void releaseAll( final List<?> components )
{
for ( final Object o : components )
{
release( o );
}
}
public void dispose()
{
disposing = true;
plexusBeanManager.unmanage();
containerRealm.setParentRealm( null );
qualifiedBeanLocator.clear();
lookupRealm.remove();
containerRealm.getWorld().removeListener( realmManager );
}
// ----------------------------------------------------------------------
// Implementation methods
// ----------------------------------------------------------------------
private static BeanScanning parseScanningOption( final String scanning )
{
for ( final BeanScanning option : BeanScanning.values() )
{
if ( option.name().equalsIgnoreCase( scanning ) )
{
return option;
}
}
return BeanScanning.OFF;
}
/**
* Finds container {@link ClassRealm}, taking existing {@link ClassWorld}s or {@link ClassLoader}s into account.
*
* @param configuration The container configuration
* @return Container class realm
*/
private static ClassRealm lookupContainerRealm( final ContainerConfiguration configuration )
throws PlexusContainerException
{
ClassRealm realm = configuration.getRealm();
if ( null == realm )
{
ClassWorld world = configuration.getClassWorld();
if ( null == world )
{
world = new ClassWorld( DEFAULT_REALM_NAME, Thread.currentThread().getContextClassLoader() );
}
try
{
realm = world.getRealm( DEFAULT_REALM_NAME );
}
catch ( final NoSuchRealmException e )
{
final Iterator<?> realmIterator = world.getRealms().iterator();
if ( realmIterator.hasNext() )
{
realm = (ClassRealm) realmIterator.next();
}
}
}
if ( null == realm )
{
throw new PlexusContainerException( "Missing container class realm: " + DEFAULT_REALM_NAME );
}
return realm;
}
/**
* Finds container configuration URL, may search the container {@link ClassRealm} and local file-system.
*
* @param configuration The container configuration
* @return Local or remote URL
*/
private URL lookupPlexusXml( final ContainerConfiguration configuration )
{
URL url = configuration.getContainerConfigurationURL();
if ( null == url )
{
final String configurationPath = configuration.getContainerConfiguration();
if ( null != configurationPath )
{
int index = 0;
while ( index < configurationPath.length() && configurationPath.charAt( index ) == '/' )
{
index++;
}
url = getClass().getClassLoader().getResource( configurationPath.substring( index ) );
if ( null == url )
{
final File file = new File( configurationPath );
if ( file.isFile() )
{
try
{
url = file.toURI().toURL();
}
catch ( final MalformedURLException e ) // NOPMD
{
// drop through and recover
}
}
}
if ( null == url )
{
getLogger().debug( "Missing container configuration: " + configurationPath );
}
}
}
return url;
}
private static Context getContextComponent( final ContainerConfiguration configuration )
{
final Map<?, ?> contextData = configuration.getContext();
final Context contextComponent = configuration.getContextComponent();
if ( null == contextComponent )
{
return new DefaultContext( contextData );
}
if ( null != contextData )
{
for ( final Entry<?, ?> entry : contextData.entrySet() )
{
contextComponent.put( entry.getKey(), entry.getValue() );
}
}
return contextComponent;
}
private <T> Iterable<PlexusBean<T>> locate( final String role, final Class<T> type, final String... hints )
{
if ( disposing )
{
return Collections.EMPTY_SET;
}
final String[] canonicalHints = Hints.canonicalHints( hints );
if ( null == role || null != type && type.getName().equals( role ) )
{
return plexusBeanLocator.locate( TypeLiteral.get( type ), canonicalHints );
}
final Set<Class> candidates = new HashSet<Class>();
for ( final ClassRealm realm : getVisibleRealms() )
{
try
{
final Class clazz = realm.loadClass( role );
if ( candidates.add( clazz ) )
{
final Iterable beans = plexusBeanLocator.locate( TypeLiteral.get( clazz ), canonicalHints );
if ( hasPlexusBeans( beans ) )
{
return beans;
}
}
}
catch ( final Exception e )
{
// drop through...
}
catch ( final LinkageError e )
{
// drop through...
}
}
return Collections.EMPTY_SET;
}
private Collection<ClassRealm> getVisibleRealms()
{
final Object[] realms = getClassWorld().getRealms().toArray();
final Set<ClassRealm> visibleRealms = new LinkedHashSet<ClassRealm>( realms.length );
final ClassRealm currentLookupRealm = getLookupRealm();
if ( null != currentLookupRealm )
{
visibleRealms.add( currentLookupRealm );
}
final ClassRealm threadContextRealm = RealmManager.contextRealm();
if ( null != threadContextRealm )
{
visibleRealms.add( threadContextRealm );
}
if ( PlexusConstants.REALM_VISIBILITY.equalsIgnoreCase( componentVisibility ) )
{
final Collection<String> realmNames = realmManager.visibleRealmNames( threadContextRealm );
if ( null != realmNames && realmNames.size() > 0 )
{
for ( int i = realms.length - 1; i >= 0; i-- )
{
final ClassRealm r = (ClassRealm) realms[i];
if ( realmNames.contains( r.toString() ) )
{
visibleRealms.add( r );
}
}
return visibleRealms;
}
}
for ( int i = realms.length - 1; i >= 0; i-- )
{
visibleRealms.add( (ClassRealm) realms[i] );
}
return visibleRealms;
}
private static <T> boolean hasPlexusBeans( final Iterable<PlexusBean<T>> beans )
{
final Iterator<PlexusBean<T>> i = beans.iterator();
return i.hasNext() && i.next().getImplementationClass() != null;
}
private static <T> ComponentDescriptor<T> newComponentDescriptor( final String role, final PlexusBean<T> bean )
{
final ComponentDescriptor<T> cd = new ComponentDescriptor<T>();
cd.setRole( role );
cd.setRoleHint( bean.getKey() );
cd.setImplementationClass( bean.getImplementationClass() );
cd.setDescription( bean.getDescription() );
return cd;
}
final class BootModule
implements Module
{
private final Module[] customBootModules;
BootModule( final Module[] customBootModules )
{
this.customBootModules = customBootModules;
}
public void configure( final Binder binder )
{
binder.requestInjection( DefaultPlexusContainer.this );
for ( final Module m : customBootModules )
{
binder.install( m );
}
}
}
final class ContainerModule
implements Module
{
public void configure( final Binder binder )
{
binder.bind( Context.class ).toInstance( context );
binder.bind( ParameterKeys.PROPERTIES ).toInstance( context.getContextData() );
binder.bind( MutableBeanLocator.class ).toInstance( qualifiedBeanLocator );
binder.bind( PlexusBeanLocator.class ).toInstance( plexusBeanLocator );
binder.bind( BeanManager.class ).toInstance( plexusBeanManager );
binder.bind( PlexusContainer.class ).to( MutablePlexusContainer.class );
binder.bind( MutablePlexusContainer.class ).to( DefaultPlexusContainer.class );
// use provider wrapper to avoid repeated injections later on when configuring plugin injectors
binder.bind( DefaultPlexusContainer.class ).toProvider( Providers.of( DefaultPlexusContainer.this ) );
}
}
final class DefaultsModule
implements Module
{
private final LoggerProvider loggerProvider = new LoggerProvider();
private final PlexusDateTypeConverter dateConverter = new PlexusDateTypeConverter();
public void configure( final Binder binder )
{
binder.bind( LoggerManager.class ).toProvider( loggerManagerProvider );
binder.bind( Logger.class ).toProvider( loggerProvider );
// allow plugins to override the default ranking function so we can support component profiles
final Key<RankingFunction> plexusRankingKey = Key.get( RankingFunction.class, Names.named( "plexus" ) );
binder.bind( plexusRankingKey ).toInstance( new DefaultRankingFunction( plexusRank.incrementAndGet() ) );
binder.bind( RankingFunction.class ).to( plexusRankingKey );
binder.install( dateConverter );
binder.bind( PlexusBeanConverter.class ).to( PlexusXmlBeanConverter.class );
}
}
final class LoggerManagerProvider
implements DeferredProvider<LoggerManager>
{
public LoggerManager get()
{
return getLoggerManager();
}
public DeferredClass<LoggerManager> getImplementationClass()
{
return new LoadedClass<LoggerManager>( get().getClass() );
}
}
final class LoggerProvider
implements DeferredProvider<Logger>
{
public Logger get()
{
return getLogger();
}
public DeferredClass<Logger> getImplementationClass()
{
return new LoadedClass<Logger>( get().getClass() );
}
}
final class SLF4JLoggerFactoryProvider
implements Provider<Object>
{
public Object get()
{
return plexusBeanLocator.locate( TypeLiteral.get( org.slf4j.ILoggerFactory.class ) ).iterator().next().getValue();
}
}
}