All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.governator.guice.BootstrapBinder Maven / Gradle / Ivy

There is a newer version: 1.17.13
Show newest version
/*
 * Copyright 2013 Netflix, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.netflix.governator.guice;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;

import org.aopalliance.intercept.MethodInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.google.inject.Binder;
import com.google.inject.Binding;
import com.google.inject.Key;
import com.google.inject.MembersInjector;
import com.google.inject.Module;
import com.google.inject.PrivateBinder;
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.binder.AnnotatedConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.matcher.Matcher;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.Message;
import com.google.inject.spi.ModuleAnnotatedMethodScanner;
import com.google.inject.spi.ProvisionListener;
import com.google.inject.spi.TypeConverter;
import com.google.inject.spi.TypeListener;
import com.netflix.governator.configuration.ConfigurationProvider;
import com.netflix.governator.lifecycle.LifecycleListener;
import com.netflix.governator.lifecycle.ResourceLocator;

public class BootstrapBinder implements Binder
{
    private final Logger log = LoggerFactory.getLogger(getClass());
    private final Binder binder;
    private Stage stage;
    private LifecycleInjectorMode mode;
    private ModuleListBuilder modules;
    private boolean disableAutoBinding;
    
    BootstrapBinder(Binder binder, Stage stage, LifecycleInjectorMode mode, ModuleListBuilder modules, Collection actions, Collection transformers, boolean disableAutoBinding)
    {
        this.binder = binder;
        this.mode = mode;
        this.stage = stage;
        this.modules = modules;
        
        Multibinder transformerBinder = Multibinder.newSetBinder(binder, ModuleTransformer.class);
        Multibinder actionBinder = Multibinder.newSetBinder(binder, PostInjectorAction.class);
        
        for (PostInjectorAction action : actions) {
            actionBinder.addBinding().toInstance(action);
        }
        
        for (ModuleTransformer transformer : transformers) {
            transformerBinder.addBinding().toInstance(transformer);
        }
    }

    private String getBindingLocation() {
    	StackTraceElement[] stack = Thread.currentThread().getStackTrace();
    	for (int i = 1; i < stack.length ; i++) {
    		StackTraceElement elem = stack[i];
    		if (!elem.getClassName().equals(BootstrapBinder.class.getCanonicalName()))
    			return elem.toString();
    	}
    	return stack[0].toString();
    }

    @Override
    public void bindInterceptor(Matcher> classMatcher, Matcher methodMatcher, MethodInterceptor... interceptors)
    {
        binder.bindInterceptor(classMatcher, methodMatcher, interceptors);
    }

    @Override
    public void bindScope(Class annotationType, Scope scope)
    {
        binder.bindScope(annotationType, scope);
    }

    /**
     * Bind actions to perform after the injector is created.
     * 
     * @return a binding builder used to add a new element in the set.
     */
    public LinkedBindingBuilder bindPostInjectorAction()
    {
        return Multibinder.newSetBinder(binder, PostInjectorAction.class).addBinding();
    }

    /**
     * Bind module transform operations to perform on the final list of modul.
     * 
     * @return a binding builder used to add a new element in the set.
     */
    public LinkedBindingBuilder bindModuleTransformer()
    {
        return Multibinder.newSetBinder(binder, ModuleTransformer.class).addBinding();
    }

    /**
     * Use this to bind a {@link LifecycleListener}. It internally uses a Multibinder to do the
     * binding so that you can bind multiple LifecycleListeners
     *
     * @return a binding builder used to add a new element in the set.
     */
    public LinkedBindingBuilder bindLifecycleListener()
    {
        return Multibinder.newSetBinder(binder, LifecycleListener.class).addBinding();
    }

    /**
     * Use this to bind a {@link ResourceLocator}. It internally uses a Multibinder to do the
     * binding so that you can bind multiple ResourceLocators
     *
     * @return a binding builder used to add a new element in the set.
     */
    public LinkedBindingBuilder bindResourceLocator()
    {
        return Multibinder.newSetBinder(binder, ResourceLocator.class).addBinding();
    }

    /**
     * Use this to bind {@link ConfigurationProvider}s. Do NOT use standard Guice binding.
     *
     * @return configuration binding builder
     */
    public LinkedBindingBuilder bindConfigurationProvider()
    {
        return Multibinder.newSetBinder(binder, ConfigurationProvider.class).addBinding();
    }

    @Override
    public  LinkedBindingBuilder bind(Key key)
    {
        warnOnSpecialized(key.getTypeLiteral().getRawType());
        return binder.withSource(getBindingLocation()).bind(key);
    }
    
    @Override
    public  AnnotatedBindingBuilder bind(TypeLiteral typeLiteral)
    {
        warnOnSpecialized(typeLiteral.getRawType());
        return binder.withSource(getBindingLocation()).bind(typeLiteral);
    }

    @Override
    public  AnnotatedBindingBuilder bind(Class type)
    {
        warnOnSpecialized(type);
        return binder.withSource(getBindingLocation()).bind(type);
    }

    @Override
    public AnnotatedConstantBindingBuilder bindConstant()
    {
        return binder.withSource(getBindingLocation()).bindConstant();
    }

    @Override
    public  void requestInjection(TypeLiteral type, T instance)
    {
        binder.withSource(getBindingLocation()).requestInjection(type, instance);
    }

    @Override
    public void requestInjection(Object instance)
    {
        binder.withSource(getBindingLocation()).requestInjection(instance);
    }

    @Override
    public void requestStaticInjection(Class... types)
    {
        binder.withSource(getBindingLocation()).requestStaticInjection(types);
    }

    @Override
    public void install(Module module)
    {
        binder.withSource(getBindingLocation()).install(module);
    }
    
    public void include(Class module) {
        this.modules.include(module);
    }
    
    public void include(Class ... modules) {
        this.modules.include(Lists.newArrayList(modules));
    }
    
    public void include(Collection> modules) {
        this.modules.include(modules);
    }
    
    public void include(Module module) {
        this.modules.include(module);
    }

    public void includeModules(Collection modules) {
        this.modules.includeModules(modules);
    }

    public void includeModules(Module ... modules) {
        this.modules.includeModules(Lists.newArrayList(modules));
    }

    public void exclude(Class module) {
        this.modules.exclude(module);
    }
    
    public void exclude(Class ... modules) {
        this.modules.exclude(Lists.newArrayList(modules));
    }
    
    public void exclude(Collection> modules) {
        this.modules.exclude(modules);
    }
    
    public void inStage(Stage stage) {
        this.stage = stage;
    }

    public void inMode(LifecycleInjectorMode mode) {
        this.mode = mode;
    }
    
    @Override
    public Stage currentStage()
    {
        return binder.currentStage();
    }

    @Override
    public void addError(String message, Object... arguments)
    {
        binder.addError(message, arguments);
    }

    @Override
    public void addError(Throwable t)
    {
        binder.addError(t);
    }

    @Override
    public void addError(Message message)
    {
        binder.addError(message);
    }

    @Override
    public  Provider getProvider(Key key)
    {
        return binder.getProvider(key);
    }

    @Override
    public  Provider getProvider(Class type)
    {
        return binder.getProvider(type);
    }

    @Override
    public  MembersInjector getMembersInjector(TypeLiteral typeLiteral)
    {
        return binder.getMembersInjector(typeLiteral);
    }

    @Override
    public  MembersInjector getMembersInjector(Class type)
    {
        return binder.getMembersInjector(type);
    }

    @Override
    public void convertToTypes(Matcher> typeMatcher, TypeConverter converter)
    {
        binder.convertToTypes(typeMatcher, converter);
    }

    @Override
    public void bindListener(Matcher> typeMatcher, TypeListener listener)
    {
        binder.withSource(getBindingLocation()).bindListener(typeMatcher, listener);
    }

    @Override
    public Binder withSource(Object source)
    {
        return binder.withSource(source);
    }

    @Override
    public Binder skipSources(@SuppressWarnings("rawtypes") Class... classesToSkip)
    {
        return binder.skipSources(classesToSkip);
    }

    @Override
    public PrivateBinder newPrivateBinder()
    {
        return binder.newPrivateBinder();
    }

    @Override
    public void requireExplicitBindings()
    {
        binder.requireExplicitBindings();
    }

    @Override
    public void disableCircularProxies()
    {
        binder.disableCircularProxies();
    }

    public void disableAutoBinding() {
        disableAutoBinding = true;
    }

    private void    warnOnSpecialized(Class clazz)
    {
        if ( ConfigurationProvider.class.isAssignableFrom(clazz) )
        {
            log.warn("You should use the specialized binding method for ConfigurationProviders");
        }
        if ( LifecycleListener.class.isAssignableFrom(clazz) )
        {
            log.warn("You should use the specialized binding method for LifecycleListener");
        }
        if ( ResourceLocator.class.isAssignableFrom(clazz) )
        {
            log.warn("You should use the specialized binding method for ResourceLocator");
        }
    }
    
    Stage getStage() {
        return stage;
    }
    
    LifecycleInjectorMode getMode() {
        return mode;
    }

    boolean isDisabledAutoBinding() {
        return disableAutoBinding;
    }

    @Override
    public  Provider getProvider(Dependency dependency) {
        return binder.getProvider(dependency);
    }

    @Override
    public void bindListener(Matcher> bindingMatcher,
            ProvisionListener... listeners) {
        binder.bindListener(bindingMatcher, listeners);
    }

    @Override
    public void requireAtInjectOnConstructors() {
        binder.requireAtInjectOnConstructors();
    }

    @Override
    public void requireExactBindingAnnotations() {
        binder.requireExactBindingAnnotations();
    }

    @Override
    public void scanModulesForAnnotatedMethods(
            ModuleAnnotatedMethodScanner scanner) {
        binder.scanModulesForAnnotatedMethods(scanner);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy