/******************************************************************************* * 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.osgi; import org.eclipse.sisu.inject.BindingSubscriber; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import com.google.inject.Binder; import com.google.inject.Binding; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.name.Names; import com.google.inject.spi.BindingScopingVisitor; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.ElementVisitor; /** * Service {@link Binding} backed by an OSGi {@link ServiceReference}. */ final class ServiceBinding<T> implements Binding<T>, Provider<T> { // ---------------------------------------------------------------------- // Implementation fields // ---------------------------------------------------------------------- private final Key<T> key; private final T instance; private final int rank; // ---------------------------------------------------------------------- // Constructors // ---------------------------------------------------------------------- ServiceBinding( final BundleContext context, final String clazzName, final int maxRank, final ServiceReference<T> reference ) throws ClassNotFoundException { @SuppressWarnings( "unchecked" ) final Class<T> clazz = (Class<T>) reference.getBundle().loadClass( clazzName ); final Object name = reference.getProperty( "name" ); if ( name instanceof String && ( (String) name ).length() > 0 ) { key = Key.get( clazz, Names.named( (String) name ) ); } else { key = Key.get( clazz ); } instance = context.getService( reference ); if ( maxRank > Integer.MIN_VALUE ) { final int serviceRanking = getServiceRanking( reference ); rank = serviceRanking < maxRank ? serviceRanking : maxRank; } else { rank = Integer.MIN_VALUE; } } // ---------------------------------------------------------------------- // Public methods // ---------------------------------------------------------------------- public Key<T> getKey() { return key; } public Provider<T> getProvider() { return this; } public T get() { return instance; } public Object getSource() { return "OSGi service registry"; } public void applyTo( final Binder binder ) { // no-op } public <V> V acceptVisitor( final ElementVisitor<V> visitor ) { return visitor.visit( this ); } public <V> V acceptTargetVisitor( final BindingTargetVisitor<? super T, V> visitor ) { return null; } public <V> V acceptScopingVisitor( final BindingScopingVisitor<V> visitor ) { return visitor.visitScopeAnnotation( Singleton.class ); } // ---------------------------------------------------------------------- // Local methods // ---------------------------------------------------------------------- boolean isCompatibleWith( final BindingSubscriber<T> subscriber ) { return key.getTypeLiteral().getRawType().equals( subscriber.type().getRawType() ); } int rank() { return rank; } // ---------------------------------------------------------------------- // Implementation methods // ---------------------------------------------------------------------- private static int getServiceRanking( final ServiceReference<?> reference ) { final Object ranking = reference.getProperty( Constants.SERVICE_RANKING ); return ranking instanceof Integer ? ( (Integer) ranking ).intValue() : 0; } }