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

jvmMain.com.giancarlobuenaflor.kflogger.util.ThrowableStackGetter Maven / Gradle / Ivy

/*
 * Copyright (C) 2021 The Flogger Authors.
 *
 * 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.giancarlobuenaflor.kflogger.util;

import static com.giancarlobuenaflor.kflogger.util.Checks.checkArgument;

/** Default implementation of {@link StackGetter} using {@link Throwable#getStackTrace}. */
final class ThrowableStackGetter implements StackGetter {

  @Override
  public StackTraceElement callerOf(Class target, int skipFrames) {
    checkArgument(skipFrames >= 0, "skipFrames must be >= 0");
    StackTraceElement[] stack = new Throwable().getStackTrace();
    int callerIndex = findCallerIndex(stack, target, skipFrames + 1);
    if (callerIndex != -1) {
      return stack[callerIndex];
    }

    return null;
  }

  @Override
  public StackTraceElement[] getStackForCaller(Class target, int maxDepth, int skipFrames) {
    checkArgument(maxDepth == -1 || maxDepth > 0, "maxDepth must be > 0 or -1");
    checkArgument(skipFrames >= 0, "skipFrames must be >= 0");
    StackTraceElement[] stack = new Throwable().getStackTrace();
    int callerIndex = findCallerIndex(stack, target, skipFrames + 1);
    if (callerIndex == -1) {
      return new StackTraceElement[0];
    }
    int elementsToAdd = stack.length - callerIndex;
    if (maxDepth > 0 && maxDepth < elementsToAdd) {
      elementsToAdd = maxDepth;
    }
    StackTraceElement[] stackTrace = new StackTraceElement[elementsToAdd];
    System.arraycopy(stack, callerIndex, stackTrace, 0, elementsToAdd);
    return stackTrace;
  }

  private int findCallerIndex(StackTraceElement[] stack, Class target, int skipFrames) {
    boolean foundCaller = false;
    String targetClassName = target.getName();
    for (int frameIndex = skipFrames; frameIndex < stack.length; frameIndex++) {
      if (stack[frameIndex].getClassName().equals(targetClassName)) {
        foundCaller = true;
      } else if (foundCaller) {
        return frameIndex;
      }
    }
    return -1;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy