package com.netflix.governator.guice.actions;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Maps;
import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.DefaultBindingTargetVisitor;
import com.google.inject.spi.DefaultElementVisitor;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.spi.LinkedKeyBinding;
import com.google.inject.spi.ProviderBinding;
import com.google.inject.spi.ProviderInstanceBinding;
import com.google.inject.spi.ProviderKeyBinding;
import com.google.inject.spi.UntargettedBinding;
import com.netflix.governator.guice.PostInjectorAction;
public class BindingReport implements PostInjectorAction {
private static final Logger LOG = LoggerFactory.getLogger(BindingReport.class);
private final String label;
public BindingReport(String label) {
this.label = label;
}
public BindingReport() {
this(">>>> GUICE BINDING REPORT <<<<");
}
@Override
public void call(Injector injector) {
LOG.info("Bindings for " + label);
LOG.info(describeBindings("Binding : ", injector.getBindings().entrySet()));
Map<Key<?>, Binding<?>> jitBindings = Maps.difference(injector.getAllBindings(), injector.getBindings()).entriesOnlyOnLeft();
LOG.info(describeBindings("JIT : ", jitBindings.entrySet()));
}
private String describeBindings(final String label, Set<Entry<Key<?>, Binding<?>>> bindings) {
final StringBuilder sb = new StringBuilder();
for (Entry<Key<?>, Binding<?>> binding : bindings) {
binding.getValue().acceptVisitor(new DefaultElementVisitor<Void>() {
@Override
public <T> Void visit(Binding<T> binding) {
sb.append("\n" + label + binding.getKey()).append("\n");
if (binding.getSource() != null) {
sb.append(" where : " + binding.getSource()).append("\n");;
}
binding.acceptTargetVisitor(new DefaultBindingTargetVisitor<T, Void>() {
public Void visit(UntargettedBinding<? extends T> untargettedBinding) {
sb.append(describeInjectionPoints(untargettedBinding.getKey().getTypeLiteral()));
return null;
}
@Override
public Void visit(InstanceBinding<? extends T> binding) {
sb.append(" to (I) : " + binding.getInstance().getClass()).append("\n");
sb.append(describeInjectionPoints(TypeLiteral.get(binding.getInstance().getClass())));
return null;
}
@Override
public Void visit(ProviderInstanceBinding<? extends T> binding) {
sb.append(" to (P) : " + binding.getProviderInstance().getClass()).append("\n");
sb.append(describeInjectionPoints(TypeLiteral.get(binding.getProviderInstance().getClass())));
return null;
}
@Override
public Void visit(ProviderKeyBinding<? extends T> binding) {
sb.append(" to (P) : " + binding.getProviderKey()).append("\n");
sb.append(describeInjectionPoints(binding.getProviderKey().getTypeLiteral()));
return null;
}
@Override
public Void visit(LinkedKeyBinding<? extends T> binding) {
sb.append(" to (I) : " + binding.getLinkedKey()).append("\n");
sb.append(describeInjectionPoints(binding.getLinkedKey().getTypeLiteral()));
return null;
}
@Override
public Void visit(ProviderBinding<? extends T> binding) {
sb.append(" to (P) : " + binding.getProvidedKey()).append("\n");
sb.append(describeInjectionPoints(binding.getProvidedKey().getTypeLiteral()));
return null;
}
});
sb.append(describeInjectionPoints(binding.getKey().getTypeLiteral()));
return null;
}
});
}
return sb.toString();
}
private String describeInjectionPoints(TypeLiteral<?> type) {
StringBuilder sb = new StringBuilder();
try {
InjectionPoint ip = InjectionPoint.forConstructorOf(type);
List<Dependency<?>> deps = ip.getDependencies();
if (!deps.isEmpty()) {
for (Dependency<?> dep : deps) {
sb.append(" dep : " + dep.getKey()).append("\n");
}
}
}
catch (Exception e) {
}
try {
Set<InjectionPoint> ips = InjectionPoint.forInstanceMethodsAndFields(type);
for (InjectionPoint ip2 : ips) {
List<Dependency<?>> deps = ip2.getDependencies();
if (!deps.isEmpty()) {
for (Dependency<?> dep : deps) {
sb.append(" mem : " + dep.getKey()).append("\n");
}
}
}
}
catch (Exception e) {
}
return sb.toString();
}
}