Home | History | Annotate | Download | only in spi
      1 /**
      2  * Copyright (C) 2013 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.inject.spi;
     18 
     19 import com.google.common.base.Preconditions;
     20 import com.google.common.collect.ImmutableList;
     21 import com.google.inject.Module;
     22 import com.google.inject.internal.util.StackTraceElements;
     23 import com.google.inject.internal.util.StackTraceElements.InMemoryStackTraceElement;
     24 
     25 import java.util.List;
     26 
     27 /**
     28  * Associated to a {@link Module module}, provides the module class name, the parent module {@link
     29  * ModuleSource source}, and the call stack that ends just before the module {@link
     30  * Module#configure(Binder) configure(Binder)} method invocation.
     31  */
     32 final class ModuleSource {
     33 
     34   /**
     35    * The class name of module that this {@link ModuleSource} associated to.
     36    */
     37   private final String moduleClassName;
     38 
     39   /**
     40    * The parent {@link ModuleSource module source}.
     41    */
     42   private final ModuleSource parent;
     43 
     44   /**
     45    * The chunk of call stack that starts from the parent module {@link Module#configure(Binder)
     46    * configure(Binder)} call and ends just before the module {@link Module#configure(Binder)
     47    * configure(Binder)} method invocation. For a module without a parent module the chunk starts
     48    * from the bottom of call stack. The array is non-empty if stack trace collection is on.
     49    */
     50   private final InMemoryStackTraceElement[] partialCallStack;
     51 
     52   /**
     53    * Creates a new {@link ModuleSource} with a {@literal null} parent.
     54    * @param module the corresponding module
     55    * @param partialCallStack the chunk of call stack that starts from the parent module {@link
     56    * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link
     57    * Module#configure(Binder) configure(Binder)} method invocation
     58    */
     59   ModuleSource(Object module, StackTraceElement[] partialCallStack) {
     60     this(null, module, partialCallStack);
     61   }
     62 
     63  /**
     64    * Creates a new {@link ModuleSource} Object.
     65    * @param parent the parent module {@link ModuleSource source}
     66    * @param module the corresponding module
     67    * @param partialCallStack the chunk of call stack that starts from the parent module {@link
     68    * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link
     69    * Module#configure(Binder) configure(Binder)} method invocation
     70    */
     71   private ModuleSource(
     72       /* @Nullable */ ModuleSource parent, Object module, StackTraceElement[] partialCallStack) {
     73     Preconditions.checkNotNull(module, "module cannot be null.");
     74     Preconditions.checkNotNull(partialCallStack, "partialCallStack cannot be null.");
     75     this.parent = parent;
     76     this.moduleClassName = module.getClass().getName();
     77     this.partialCallStack = StackTraceElements.convertToInMemoryStackTraceElement(partialCallStack);
     78   }
     79 
     80   /**
     81    * Returns the corresponding module class name.
     82    *
     83    * @see Class#getName()
     84    */
     85   String getModuleClassName() {
     86     return moduleClassName;
     87   }
     88 
     89   /**
     90    * Returns the chunk of call stack that starts from the parent module {@link
     91    * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link
     92    * Module#configure(Binder) configure(Binder)} method invocation. The return array is non-empty
     93    * only if stack trace collection is on.
     94    */
     95   StackTraceElement[] getPartialCallStack() {
     96     return StackTraceElements.convertToStackTraceElement(partialCallStack);
     97   }
     98 
     99   /**
    100    * Returns the size of partial call stack if stack trace collection is on otherwise zero.
    101    */
    102   int getPartialCallStackSize() {
    103     return partialCallStack.length;
    104   }
    105 
    106   /**
    107    * Creates and returns a child {@link ModuleSource} corresponding to the {@link Module module}.
    108    * @param module the corresponding module
    109    * @param partialCallStack the chunk of call stack that starts from the parent module {@link
    110    * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link
    111    * Module#configure(Binder) configure(Binder)} method invocation
    112    */
    113   ModuleSource createChild(Object module, StackTraceElement[] partialCallStack) {
    114     return new ModuleSource(this, module, partialCallStack);
    115   }
    116 
    117   /**
    118    * Returns the parent module {@link ModuleSource source}.
    119    */
    120   ModuleSource getParent() {
    121     return parent;
    122   }
    123 
    124   /**
    125    * Returns the class names of modules in this module source. The first element (index 0) is filled
    126    * by this object {@link #getModuleClassName()}. The second element is filled by the parent's
    127    * {@link #getModuleClassName()} and so on.
    128    */
    129   List<String> getModuleClassNames() {
    130     ImmutableList.Builder<String> classNames = ImmutableList.builder();
    131     ModuleSource current = this;
    132     while (current != null) {
    133       String className = current.moduleClassName;
    134       classNames.add(className);
    135       current = current.parent;
    136     }
    137     return classNames.build();
    138   }
    139 
    140   /**
    141    * Returns the size of {@link ModuleSource ModuleSources} chain (all parents) that ends at this
    142    * object.
    143    */
    144   int size() {
    145     if (parent == null) {
    146       return 1;
    147     }
    148     return parent.size() + 1;
    149   }
    150 
    151   /**
    152    * Returns the size of call stack that ends just before the module {@link Module#configure(Binder)
    153    * configure(Binder)} method invocation (see {@link #getStackTrace()}).
    154    */
    155   int getStackTraceSize() {
    156     if (parent == null) {
    157       return partialCallStack.length;
    158     }
    159     return parent.getStackTraceSize() + partialCallStack.length;
    160   }
    161 
    162   /**
    163    * Returns the full call stack that ends just before the module {@link Module#configure(Binder)
    164    * configure(Binder)} method invocation. The return array is non-empty if stack trace collection
    165    * on.
    166    */
    167   StackTraceElement[] getStackTrace() {
    168     int stackTraceSize = getStackTraceSize();
    169     StackTraceElement[] callStack = new StackTraceElement[stackTraceSize];
    170     int cursor = 0;
    171     ModuleSource current = this;
    172     while (current != null) {
    173       StackTraceElement[] chunk =
    174           StackTraceElements.convertToStackTraceElement(current.partialCallStack);
    175       int chunkSize = chunk.length;
    176       System.arraycopy(chunk, 0, callStack, cursor, chunkSize);
    177       current = current.parent;
    178       cursor = cursor + chunkSize;
    179     }
    180     return callStack;
    181   }
    182 }
    183