| /******************************************************************************* |
| * 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; |
| } |
| }; |
| } |
| } |