blob: 982e32c3d3ce9b7eb1f081966e722b6564e4b97b [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
*******************************************************************************/
package org.eclipse.sisu.inject;
import javax.inject.Provider;
import com.google.inject.Binding;
import com.google.inject.Scopes;
import com.google.inject.spi.ProviderInstanceBinding;
/**
* Utility methods for dealing with changes in the Guice 4.0 SPI.
*/
public final class Guice4
{
// ----------------------------------------------------------------------
// Static initialization
// ----------------------------------------------------------------------
static
{
boolean hasDeclaringSource;
try
{
// in Guice4 binding.getSource() returns ElementSource and not the original declaring source
hasDeclaringSource = com.google.inject.spi.ElementSource.class.getMethod( "getDeclaringSource" ) != null; // NOSONAR
}
catch ( final Exception e )
{
hasDeclaringSource = false;
}
catch ( final LinkageError e )
{
hasDeclaringSource = false;
}
HAS_DECLARING_SOURCE = hasDeclaringSource;
boolean hasUserSuppliedProvider;
try
{
// in Guice4 getProviderInstance() is deprecated in favour of getUserSuppliedProvider()
hasUserSuppliedProvider = ProviderInstanceBinding.class.getMethod( "getUserSuppliedProvider" ) != null; // NOSONAR
}
catch ( final Exception e )
{
hasUserSuppliedProvider = false;
}
catch ( final LinkageError e )
{
hasUserSuppliedProvider = false;
}
HAS_USER_SUPPLIED_PROVIDER = hasUserSuppliedProvider;
boolean hasOldScopesSingleton;
try
{
// in Guice4 using Scopes.SINGLETON.scope(...) outside of the Injector is deprecated
hasOldScopesSingleton = Scopes.class.equals( Scopes.SINGLETON.getClass().getEnclosingClass() ) //
&& Scopes.SINGLETON.scope( null /* key */, null /* provider */ ) != null;
}
catch ( final Exception e )
{
hasOldScopesSingleton = false;
}
catch ( final LinkageError e )
{
hasOldScopesSingleton = false;
}
HAS_OLD_SCOPES_SINGLETON = hasOldScopesSingleton;
}
// ----------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------
private static final boolean HAS_DECLARING_SOURCE;
private static final boolean HAS_USER_SUPPLIED_PROVIDER;
private static final boolean HAS_OLD_SCOPES_SINGLETON;
static final Object NIL = new Object();
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
private Guice4()
{
// static utility class, not allowed to create instances
}
// ----------------------------------------------------------------------
// Utility methods
// ----------------------------------------------------------------------
/**
* Returns the source that originally declared the given binding.
*
* @param binding The binding
* @return Declaring source; {@code null} if it doesn't exist
*/
public static Object getDeclaringSource( final Binding<?> binding )
{
final Object source = binding.getSource();
if ( HAS_DECLARING_SOURCE && source instanceof com.google.inject.spi.ElementSource )
{
return ( (com.google.inject.spi.ElementSource) source ).getDeclaringSource();
}
return source;
}
/**
* Returns the provider that originally backed the given binding.
*
* @param binding The binding
* @return Provider instance
*/
@SuppressWarnings( "deprecation" )
public static Provider<?> getProviderInstance( final ProviderInstanceBinding<?> binding )
{
return HAS_USER_SUPPLIED_PROVIDER ? binding.getUserSuppliedProvider() : binding.getProviderInstance();
}
/**
* Returns a lazy provider that only uses the binding once and caches the result.
*
* @param binding The binding
* @return Lazy caching provider
*/
@SuppressWarnings( "unchecked" )
public static <T> Provider<T> lazy( final Binding<T> binding )
{
if ( HAS_OLD_SCOPES_SINGLETON )
{
// avoids introducing extra locks, but won't be supported going forwards
return Scopes.SINGLETON.scope( binding.getKey(), binding.getProvider() );
}
// future behaviour: lazy holder with its own lock
final Provider<T> provider = binding.getProvider();
return new Provider<T>()
{
private volatile Object value = NIL;
public T get()
{
if ( NIL == value )
{
synchronized ( this )
{
if ( NIL == value )
{
value = provider.get();
}
}
}
return (T) value;
}
};
}
}