blob: 46e173e0bceb486dda3e9b06aa3ac75d1bab032d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2013 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.launch;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.inject.Inject;
import org.eclipse.sisu.inject.BeanLocator;
import org.eclipse.sisu.inject.Logs;
import org.eclipse.sisu.wire.WireModule;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.util.Providers;
public final class SisuGuice
{
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
private static final ThreadLocal<BeanLocator> LOCATOR = new InheritableThreadLocal<BeanLocator>();
private static volatile BeanLocator latest;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
private SisuGuice()
{
// static utility class, not allowed to create instances
}
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
@Inject
public static void setBeanLocator( final BeanLocator locator )
{
if ( null != locator )
{
LOCATOR.set( locator );
}
else
{
LOCATOR.remove();
}
latest = locator;
}
public static BeanLocator getBeanLocator()
{
final BeanLocator locator = LOCATOR.get();
return null != locator ? locator : latest;
}
public static <T> T lookup( final Key<T> key )
{
final BeanLocator locator = getBeanLocator();
if ( null != locator )
{
final Iterator<? extends Entry<?, T>> i = locator.locate( key ).iterator();
if ( i.hasNext() )
{
return i.next().getValue();
}
}
else
{
Logs.trace( "No BeanLocator found for thread {}", Thread.currentThread(), null );
}
return null;
}
public static void inject( final Object that )
{
final BeanLocator locator = getBeanLocator();
if ( null != locator )
{
Guice.createInjector( new WireModule()
{
@Override
public void configure( final Binder binder )
{
binder.bind( BeanLocator.class ).toProvider( Providers.of( locator ) );
binder.requestInjection( that );
}
} );
}
else
{
Logs.trace( "No BeanLocator found for thread {}", Thread.currentThread(), null );
}
}
public static Injector enhance( final Injector injector )
{
final Class<?>[] api = { Injector.class };
return (Injector) Proxy.newProxyInstance( api[0].getClassLoader(), api, new InvocationHandler()
{
@SuppressWarnings( { "rawtypes", "unchecked" } )
public Object invoke( final Object proxy, final Method method, final Object[] args )
throws Throwable
{
final String methodName = method.getName();
if ( "getInstance".equals( methodName ) )
{
final Key key = args[0] instanceof Key ? (Key) args[0] : Key.get( (Class) args[0] );
final Iterator<Entry> i = injector.getInstance( BeanLocator.class ).locate( key ).iterator();
return i.hasNext() ? i.next().getValue() : null;
}
if ( "injectMembers".equals( methodName ) )
{
Guice.createInjector( new WireModule( new Module()
{
public void configure( final Binder binder )
{
binder.bind( BeanLocator.class ).toProvider( injector.getProvider( BeanLocator.class ) );
binder.requestInjection( args[0] );
}
} ) );
return null;
}
return method.invoke( injector, args );
}
} );
}
}