org.eclipse.sisu.inject.Implementations Maven / Gradle / Ivy
/*******************************************************************************
* 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 java.lang.annotation.Annotation;
import javax.inject.Provider;
import org.eclipse.sisu.Description;
import org.eclipse.sisu.Priority;
import com.google.inject.Binding;
import com.google.inject.spi.BindingTargetVisitor;
import com.google.inject.spi.ConstructorBinding;
import com.google.inject.spi.DefaultBindingTargetVisitor;
import com.google.inject.spi.ExposedBinding;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.spi.LinkedKeyBinding;
import com.google.inject.spi.ProviderInstanceBinding;
import com.google.inject.spi.ProviderKeyBinding;
import com.google.inject.spi.UntargettedBinding;
/**
* Utility methods for discovering the implementations behind Guice bindings.
*/
final class Implementations
{
// ----------------------------------------------------------------------
// Static initialization
// ----------------------------------------------------------------------
static
{
boolean hasGuiceServlet;
try
{
hasGuiceServlet = BindingTargetVisitor.class.isInstance( ServletFinder.THIS );
}
catch ( final LinkageError e )
{
hasGuiceServlet = false;
}
HAS_GUICE_SERVLET = hasGuiceServlet;
boolean hasJsr250Priority;
try
{
hasJsr250Priority = javax.annotation.Priority.class.isAnnotation();
}
catch ( final LinkageError e )
{
hasJsr250Priority = false;
}
HAS_JSR250_PRIORITY = hasJsr250Priority;
}
// ----------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------
private static final boolean HAS_GUICE_SERVLET;
private static final boolean HAS_JSR250_PRIORITY;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
private Implementations()
{
// static utility class, not allowed to create instances
}
// ----------------------------------------------------------------------
// Utility methods
// ----------------------------------------------------------------------
/**
* Attempts to find the implementation behind the given {@link Binding}.
*
* @param binding The binding
* @return Implementation class behind the binding; {@code null} if it couldn't be found
*/
public static Class> find( final Binding> binding )
{
return binding.acceptTargetVisitor( ClassFinder.THIS );
}
/**
* Attempts to find an annotation on the implementation behind the given {@link Binding}.
*
* @param binding The binding
* @param annotationType The annotation type
* @return Annotation on the bound implementation; {@code null} if it couldn't be found
*/
public static T getAnnotation( final Binding> binding, final Class annotationType )
{
final boolean isPriority = Priority.class.equals( annotationType );
final Class> annotationSource =
// when looking for @Priority also consider annotations on providers (and servlets/filters if available)
binding.acceptTargetVisitor( isPriority ? ( HAS_GUICE_SERVLET ? ServletFinder.THIS : ProviderFinder.THIS )
: ClassFinder.THIS );
T annotation = null;
if ( null != annotationSource )
{
annotation = annotationSource.getAnnotation( annotationType );
if ( null == annotation )
{
if ( HAS_JSR250_PRIORITY && isPriority )
{
annotation = adaptJsr250( binding, annotationSource );
}
else if ( Description.class.equals( annotationType ) )
{
annotation = adaptLegacy( binding, annotationSource );
}
}
}
return annotation;
}
// ----------------------------------------------------------------------
// Implementation methods
// ----------------------------------------------------------------------
@SuppressWarnings( "unchecked" )
private static T adaptJsr250( final Binding> binding, final Class> clazz )
{
final javax.annotation.Priority jsr250 = clazz.getAnnotation( javax.annotation.Priority.class );
return null != jsr250 ? (T) new PrioritySource( binding.getSource(), jsr250.value() ) : null;
}
@SuppressWarnings( { "unchecked", "deprecation" } )
private static T adaptLegacy( final Binding> binding, final Class> clazz )
{
final org.sonatype.inject.Description legacy = clazz.getAnnotation( org.sonatype.inject.Description.class );
return null != legacy ? (T) new DescriptionSource( binding.getSource(), legacy.value() ) : null;
}
// ----------------------------------------------------------------------
// Implementation types
// ----------------------------------------------------------------------
/**
* {@link BindingTargetVisitor} that attempts to find the implementations behind bindings.
*/
static class ClassFinder
extends DefaultBindingTargetVisitor