blob: b36cea88df996f06d02353d234986c11497b160b [file] [log] [blame]
limpbizkit6663d022008-06-19 07:57:55 +00001/**
2 * Copyright (C) 2006 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
limpbizkit@gmail.com9a227be2010-07-03 15:51:31 +000017package com.google.inject.internal.util;
limpbizkit6663d022008-06-19 07:57:55 +000018
Christian Edward Gruber605bd082013-08-09 11:04:00 -070019import com.google.common.base.Preconditions;
sberlind9c913a2011-06-26 21:02:54 +000020import com.google.common.collect.ImmutableSet;
21import com.google.common.collect.Lists;
22
sberlinb7a02b02011-07-08 00:34:16 +000023import java.util.List;
24
limpbizkit6663d022008-06-19 07:57:55 +000025/**
26 * Provides access to the calling line of code.
27 *
28 * @author crazybob@google.com (Bob Lee)
29 */
limpbizkit5ae41eb2009-06-06 17:51:27 +000030public final class SourceProvider {
limpbizkit6663d022008-06-19 07:57:55 +000031
32 /** Indicates that the source is unknown. */
33 public static final Object UNKNOWN_SOURCE = "[unknown source]";
34
Christian Edward Gruberd9e05452013-06-26 14:34:13 -070035 private final SourceProvider parent;
limpbizkit6663d022008-06-19 07:57:55 +000036 private final ImmutableSet<String> classNamesToSkip;
Christian Edward Gruberd9e05452013-06-26 14:34:13 -070037
limpbizkit6663d022008-06-19 07:57:55 +000038 public static final SourceProvider DEFAULT_INSTANCE
39 = new SourceProvider(ImmutableSet.of(SourceProvider.class.getName()));
40
41 private SourceProvider(Iterable<String> classesToSkip) {
Christian Edward Gruberd9e05452013-06-26 14:34:13 -070042 this(null, classesToSkip);
43 }
44
45 private SourceProvider(SourceProvider parent, Iterable<String> classesToSkip) {
46 this.parent = parent;
47
48 ImmutableSet.Builder<String> classNamesToSkipBuilder = ImmutableSet.builder();
49 for (String classToSkip : classesToSkip) {
50 if (parent == null || !parent.shouldBeSkipped(classToSkip)) {
51 classNamesToSkipBuilder.add(classToSkip);
52 }
53 }
54 this.classNamesToSkip = classNamesToSkipBuilder.build();
limpbizkit6663d022008-06-19 07:57:55 +000055 }
56
57 /** Returns a new instance that also skips {@code moreClassesToSkip}. */
58 public SourceProvider plusSkippedClasses(Class... moreClassesToSkip) {
Christian Edward Gruberd9e05452013-06-26 14:34:13 -070059 return new SourceProvider(this, asStrings(moreClassesToSkip));
limpbizkit6663d022008-06-19 07:57:55 +000060 }
61
Christian Edward Gruberd9e05452013-06-26 14:34:13 -070062 /** Returns true if the className should be skipped. */
63 private boolean shouldBeSkipped(String className) {
64 if ((parent != null && parent.shouldBeSkipped(className))
65 || classNamesToSkip.contains(className)) {
66 return true;
67 }
68 return false;
69 }
70
limpbizkit6663d022008-06-19 07:57:55 +000071 /** Returns the class names as Strings */
72 private static List<String> asStrings(Class... classes) {
73 List<String> strings = Lists.newArrayList();
74 for (Class c : classes) {
75 strings.add(c.getName());
76 }
77 return strings;
78 }
79
limpbizkit6663d022008-06-19 07:57:55 +000080 /**
81 * Returns the calling line of code. The selected line is the nearest to the top of the stack that
82 * is not skipped.
83 */
Christian Edward Gruber605bd082013-08-09 11:04:00 -070084 public StackTraceElement get(StackTraceElement[] stackTraceElements) {
85 Preconditions.checkNotNull(stackTraceElements, "The stack trace elements cannot be null.");
86 for (final StackTraceElement element : stackTraceElements) {
limpbizkit6663d022008-06-19 07:57:55 +000087 String className = element.getClassName();
Christian Edward Gruberd9e05452013-06-26 14:34:13 -070088
89 if (!shouldBeSkipped(className)) {
limpbizkit6663d022008-06-19 07:57:55 +000090 return element;
91 }
92 }
93 throw new AssertionError();
94 }
Christian Edward Gruberba5acdf2013-10-05 14:05:39 -070095
96 /**
97 * Returns the non-skipped module class name.
98 */
99 public Object getFromClassNames(List<String> moduleClassNames) {
100 Preconditions.checkNotNull(moduleClassNames, "The list of module class names cannot be null.");
101 for (final String moduleClassName : moduleClassNames) {
102 if (!shouldBeSkipped(moduleClassName)) {
103 return new StackTraceElement(moduleClassName, "configure", null, -1);
104 }
105 }
106 return UNKNOWN_SOURCE;
107 }
limpbizkit6663d022008-06-19 07:57:55 +0000108}