View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.util;
18  
19  import java.util.NoSuchElementException;
20  import java.util.Stack;
21  import java.util.function.Predicate;
22  
23  import org.apache.logging.log4j.status.StatusLogger;
24  
25  /**
26   * <em>Consider this class private.</em> Provides various methods to determine the caller class. <h3>Background</h3>
27   */
28  public final class StackLocatorUtil {
29      private static StackLocator stackLocator = null;
30      private static volatile boolean errorLogged;
31  
32      static {
33          stackLocator = StackLocator.getInstance();
34      }
35  
36      private StackLocatorUtil() {
37      }
38  
39      // TODO: return Object.class instead of null (though it will have a null ClassLoader)
40      // (MS) I believe this would work without any modifications elsewhere, but I could be wrong
41  
42      // migrated from ReflectiveCallerClassUtility
43      @PerformanceSensitive
44      public static Class<?> getCallerClass(final int depth) {
45          return stackLocator.getCallerClass(depth + 1);
46      }
47  
48      public static StackTraceElement getStackTraceElement(final int depth) {
49          return stackLocator.getStackTraceElement(depth + 1);
50      }
51  
52      /**
53       * Equivalent to {@link #getCallerClass(String, String)} with an empty {@code pkg}.
54       */
55      // migrated from ClassLoaderContextSelector
56      @PerformanceSensitive
57      public static Class<?> getCallerClass(final String fqcn) {
58          return getCallerClass(fqcn, Strings.EMPTY);
59      }
60  
61      /**
62       * Search for a calling class.
63       *
64       * @param fqcn Root class name whose caller to search for.
65       * @param pkg Package name prefix that must be matched after the {@code fqcn} has been found.
66       * @return The caller class that was matched, or null if one could not be located.
67       */
68      @PerformanceSensitive
69      public static Class<?> getCallerClass(final String fqcn, final String pkg) {
70          return stackLocator.getCallerClass(fqcn, pkg);
71      }
72  
73      /**
74       * Search for a calling class.
75       *
76       * @param sentinelClass Sentinel class at which to begin searching
77       * @param callerPredicate Predicate checked after the sentinelClass is found
78       * @return the first matching class after <code>sentinelClass</code> is found.
79       */
80      @PerformanceSensitive
81      public static Class<?> getCallerClass(final Class<?> sentinelClass, final Predicate<Class<?>> callerPredicate) {
82          return stackLocator.getCallerClass(sentinelClass, callerPredicate);
83      }
84  
85      // added for use in LoggerAdapter implementations mainly
86      @PerformanceSensitive
87      public static Class<?> getCallerClass(final Class<?> anchor) {
88          return stackLocator.getCallerClass(anchor);
89      }
90  
91      // migrated from ThrowableProxy
92      @PerformanceSensitive
93      public static Stack<Class<?>> getCurrentStackTrace() {
94          return stackLocator.getCurrentStackTrace();
95      }
96  
97      public static StackTraceElement calcLocation(final String fqcnOfLogger) {
98          try {
99              return stackLocator.calcLocation(fqcnOfLogger);
100         } catch (NoSuchElementException ex) {
101             if (!errorLogged) {
102                 errorLogged = true;
103                 StatusLogger.getLogger().warn("Unable to locate stack trace element for {}", fqcnOfLogger, ex);
104             }
105             return null;
106         }
107     }
108 }