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

com.github.dxee.dject.trace.TracingProvisionListener Maven / Gradle / Ivy

package com.github.dxee.dject.trace;

import java.io.PrintStream;

import com.google.common.base.Strings;
import com.google.inject.spi.ProvisionListener;

/**
 * Use TracingProvisionListener to debug issues with Guice Injector creation by tracing
 * the object initialization path.  Various hooks are provided for the different stages
 * of object instantiation: before, after and on error.
 * 

* To enable add the following binding in any guice module *

* * bindListener(Matchers.any(), TracingProvisionListener.createDefault()); * */ public class TracingProvisionListener implements ProvisionListener { private int indent = 0; private final String prefix; private final int indentAmount; private final BindingFormatter beforeFormatter; private final BindingFormatter afterFormatter; private final PrintStream stream; private ErrorFormatter errorFormatter; private static final BindingFormatter EMPTY_BINDING_FORMATTER = new BindingFormatter() { @Override public String format(ProvisionInvocation provision) { return ""; } }; private static final BindingFormatter SIMPLE_BINDING_FORMATTER = new BindingFormatter() { @Override public String format(ProvisionInvocation provision) { return provision.getBinding().getKey().toString(); } }; private static final ErrorFormatter SIMPLE_ERROR_FORMATTER = new ErrorFormatter() { @Override public String format(ProvisionInvocation provision, Throwable t) { return String.format("Error creating '%s'. %s", provision.getBinding().getKey().toString(), t.getMessage()); } }; /** * Builder for customizing the tracer output. */ public static class Builder { private String prefix = ""; private int indentAmount = 2; private BindingFormatter beforeFormatter = SIMPLE_BINDING_FORMATTER; private BindingFormatter afterFormatter = EMPTY_BINDING_FORMATTER; private ErrorFormatter errorFormatter = SIMPLE_ERROR_FORMATTER; private PrintStream stream = System.out; /** * Provide a custom formatter for messages written before a type is provisioned * Returning null or empty stream will result in no message being written * * @param formatter */ public Builder formatBeforeWith(BindingFormatter formatter) { this.beforeFormatter = formatter; return this; } /** * Provide a custom formatter for messages written after a type is provisioned. * Returning null or empty stream will result in no message being written * * @param formatter */ public Builder formatAfterWith(BindingFormatter formatter) { this.afterFormatter = formatter; return this; } /** * Provide a custom formatter for messages written when type metrics throws * an exception * * @param formatter */ public Builder formatErrorsWith(ErrorFormatter formatter) { this.errorFormatter = formatter; return this; } /** * Indentation increment for each nested provisioning * * @param amount - Number of spaces to indent */ public Builder indentBy(int amount) { this.indentAmount = amount; return this; } /** * Customized the PrintStream to which messages are written. By default * messages are written to System.err * * @param stream */ public Builder writeTo(PrintStream stream) { this.stream = stream; return this; } /** * String to prefix each row (prior to indentation). Default is "" * * @param prefix */ public Builder prefixLinesWith(String prefix) { this.prefix = prefix; return this; } public TracingProvisionListener build() { return new TracingProvisionListener(this); } } public interface BindingFormatter { String format(ProvisionInvocation provision); } public interface ErrorFormatter { String format(ProvisionInvocation provision, Throwable error); } public static TracingProvisionListener createDefault() { return new TracingProvisionListener(builder()); } public static Builder builder() { return new Builder(); } private TracingProvisionListener(Builder builder) { this.indentAmount = builder.indentAmount; this.beforeFormatter = builder.beforeFormatter; this.afterFormatter = builder.afterFormatter; this.errorFormatter = builder.errorFormatter; this.prefix = builder.prefix; this.stream = builder.stream; } @Override public void onProvision(ProvisionInvocation provision) { writeString(beforeFormatter.format(provision)); indent += indentAmount; try { provision.provision(); writeString(afterFormatter.format(provision)); } catch (Throwable t) { writeString(errorFormatter.format(provision, t)); throw t; } finally { indent -= indentAmount; } } private void writeString(String str) { if (str != null && !str.isEmpty()) { stream.println(prefix + Strings.repeat(" ", indent) + str); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy