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

com.google.inject.spi.ElementSource Maven / Gradle / Ivy

There is a newer version: 7.0.0
Show newest version
/**
 * Copyright (C) 2013 Google 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.google.inject.spi;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.inject.internal.util.StackTraceElements;
import com.google.inject.internal.util.StackTraceElements.InMemoryStackTraceElement;

import java.util.List;

/**
 * Contains information about where and how an {@link Element element} was
 * bound.
 * 

* The {@link #getDeclaringSource() declaring source} refers to a location in * source code that defines the Guice {@link Element element}. For example, if * the element is created from a method annotated by {@literal @Provides}, the * declaring source of element would be the method itself. *

* The {@link #getStackTrace()} refers to the sequence of calls ends at one of * {@link com.google.inject.Binder} {@code bindXXX()} methods and eventually * defines the element. Note that {@link #getStackTrace()} lists * {@link StackTraceElement StackTraceElements} in reverse chronological order. * The first element (index zero) is the last method call and the last element * is the first method invocation. By default, the stack trace is not collected. * The default behavior can be changed by setting the * {@code guice_include_stack_traces} flag value. The value can be either * {@code OFF}, {@code ONLY_FOR_DECLARING_SOURCE} or {@code COMPLETE}. Note that * collecting stack traces for every binding can cause a performance hit when * the injector is created. *

* The sequence of class names of {@link com.google.inject.Module modules} * involved in the element creation can be retrieved by * {@link #getModuleClassNames()}. Similar to {@link #getStackTrace()}, the * order is reverse chronological. The first module (index 0) is the module that * installs the {@link Element element}. The last module is the root module. *

* In order to support the cases where a Guice {@link Element element} is * created from another Guice {@link Element element} (original) (e.g., by * {@link Element#applyTo}), it also provides a reference to the original * element source ({@link #getOriginalElementSource()}). * * @since 4.0 */ public final class ElementSource { /** * The {@link ElementSource source} of element that this element created from (if there is any), * otherwise {@code null}. */ final ElementSource originalElementSource; /** The {@link ModuleSource source} of module creates the element. */ final ModuleSource moduleSource; /** * The partial call stack that starts at the last module {@link Module#Configure(Binder) * configure(Binder)} call. The value is empty if stack trace collection is off. */ final InMemoryStackTraceElement[] partialCallStack; /** * Refers to a single location in source code that causes the element creation. It can be any * object such as {@link Constructor}, {@link Method}, {@link Field}, {@link StackTraceElement}, * etc. For example, if the element is created from a method annotated by {@literal @Provides}, * the declaring source of element would be the method itself. */ final Object declaringSource; /** * Creates a new {@ElementSource} from the given parameters. * @param originalElementSource The source of element that this element created from (if there is * any), otherwise {@code null}. * @param declaringSource the source (in)directly declared the element. * @param moduleSource the moduleSource when the element is bound * @param partialCallStack the partial call stack from the top module to where the element is * bound */ ElementSource(/* @Nullable */ ElementSource originalSource, Object declaringSource, ModuleSource moduleSource, StackTraceElement[] partialCallStack) { Preconditions.checkNotNull(declaringSource, "declaringSource cannot be null."); Preconditions.checkNotNull(moduleSource, "moduleSource cannot be null."); Preconditions.checkNotNull(partialCallStack, "partialCallStack cannot be null."); this.originalElementSource = originalSource; this.declaringSource = declaringSource; this.moduleSource = moduleSource; this.partialCallStack = StackTraceElements.convertToInMemoryStackTraceElement(partialCallStack); } /** * Returns the {@link ElementSource} of the element this was created or copied from. If this was * not created or copied from another element, returns {@code null}. */ public ElementSource getOriginalElementSource() { return originalElementSource; } /** * Returns a single location in source code that defines the element. It can be any object * such as {@link java.lang.reflect.Constructor}, {@link java.lang.reflect.Method}, * {@link java.lang.reflect.Field}, {@link StackTraceElement}, etc. For * example, if the element is created from a method annotated by {@literal @Provides}, the * declaring source of element would be the method itself. */ public Object getDeclaringSource() { return declaringSource; } /** * Returns the class names of modules involved in creating this {@link Element}. The first * element (index 0) is the class name of module that defined the element, and the last element * is the class name of root module. */ public List getModuleClassNames() { return moduleSource.getModuleClassNames(); } /** * Returns the position of {@link com.google.inject.Module#configure configure(Binder)} method * call in the {@link #getStackTrace stack trace} for modules that their classes returned by * {@link #getModuleClassNames}. For example, if the stack trace looks like the following: *

* {@code * 0 - Binder.bind(), * 1 - ModuleTwo.configure(), * 2 - Binder.install(), * 3 - ModuleOne.configure(), * 4 - theRest(). * } *

* 1 and 3 are returned. *

* In the cases where stack trace is not available (i.e., the stack trace was not collected), * it returns -1 for all module positions. */ public List getModuleConfigurePositionsInStackTrace() { int size = moduleSource.size(); Integer[] positions = new Integer[size]; int chunkSize = partialCallStack.length; positions[0] = chunkSize - 1; ModuleSource current = moduleSource; for (int cursor = 1; cursor < size; cursor++) { chunkSize = current.getPartialCallStackSize(); positions[cursor] = positions[cursor - 1] + chunkSize; current = current.getParent(); } return ImmutableList.copyOf(positions); } /** * Returns the sequence of method calls that ends at one of {@link com.google.inject.Binder} * {@code bindXXX()} methods and eventually defines the element. Note that * {@link #getStackTrace} lists {@link StackTraceElement StackTraceElements} in reverse * chronological order. The first element (index zero) is the last method call and the last * element is the first method invocation. In the cases where stack trace is not available * (i.e.,the stack trace was not collected), it returns an empty array. */ public StackTraceElement[] getStackTrace() { int modulesCallStackSize = moduleSource.getStackTraceSize(); int chunkSize = partialCallStack.length; int size = moduleSource.getStackTraceSize() + chunkSize; StackTraceElement[] callStack = new StackTraceElement[size]; System.arraycopy( StackTraceElements.convertToStackTraceElement(partialCallStack), 0, callStack, 0, chunkSize); System.arraycopy(moduleSource.getStackTrace(), 0, callStack, chunkSize, modulesCallStackSize); return callStack; } /** * Returns {@code getDeclaringSource().toString()} value. */ @Override public String toString() { return getDeclaringSource().toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy