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

patterntesting.runtime.util.StackTraceScanner Maven / Gradle / Ivy

Go to download

PatternTesting Runtime (patterntesting-rt) is the runtime component for the PatternTesting framework. It provides the annotations and base classes for the PatternTesting testing framework (e.g. patterntesting-check, patterntesting-concurrent or patterntesting-exception) but can be also used standalone for classpath monitoring or profiling. It uses AOP and AspectJ to perform this feat.

There is a newer version: 2.4.0
Show newest version
/*
 * $Id: StackTraceScanner.java,v 1.4 2014/02/07 16:56:53 oboehm Exp $
 *
 * Copyright (c) 2014 by Oliver Boehm
 *
 * 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 orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 24.01.2014 by oliver ([email protected])
 */

package patterntesting.runtime.util;

import java.lang.reflect.Method;
import java.util.regex.Pattern;

import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.*;
import org.slf4j.*;

import patterntesting.runtime.exception.NotFoundException;

/**
 * This class allows you to scan the stacktrace for different stuff.
 *
 * @author oliver
 * @since 1.4.1 (24.01.2014)
 */
public final class StackTraceScanner {

    private static final Logger log = LoggerFactory.getLogger(StackTraceScanner.class);

    /** Utility class - no need to instantiate it. */
    private StackTraceScanner() {}

    /**
     * Find the constructor of the given class on the stack trace.
     *
     * @param clazz the clazz
     * @return the stack trace element
     */
    public static StackTraceElement findConstructor(final Class clazz) {
        return find (clazz.getName(), "");
    }

    /**
     * Find the given signature on the stack trace.
     *
     * @param signature the signature
     * @return the stack trace element
     */
    public static StackTraceElement find(final Signature signature) {
        if (signature instanceof MethodSignature) {
            return find((MethodSignature) signature);
        } else if (signature instanceof ConstructorSignature) {
            return find((ConstructorSignature) signature);
        } else {
            throw new IllegalArgumentException(signature + " is not a method or ctor signature");
        }
    }

    private static StackTraceElement find(final ConstructorSignature signature) {
        return findConstructor(signature.getDeclaringType());
    }

    private static StackTraceElement find(final MethodSignature signature) {
        return find(signature.getDeclaringType(), signature.getMethod());
    }

    /**
     * Find the given method on the stack trace.
     *
     * @param clazz the clazz
     * @param method the method
     * @return the stack trace element
     */
    public static StackTraceElement find(final Class clazz, final Method method) {
        return find (clazz.getName(), method.getName());
    }

    /**
     * Find the given method on the stack trace.
     *
     * @param clazz the clazz
     * @param methodName the method name
     * @return the stack trace element
     */
    public static StackTraceElement find(final Class clazz, final String methodName) {
        return find (clazz.getName(), methodName);
    }

    /**
     * Find the given method on the stack trace.
     *
     * @param classname the classname
     * @param methodName the method name
     * @return the stack trace element
     */
    public static StackTraceElement find(final String classname, final String methodName) {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        int i = getIndexOf(classname, methodName, stackTrace);
        return stackTrace[i];
    }

    /**
     * Gets the caller of a constructor.
     *
     * @param clazz the clazz
     * @return the caller of constructor
     */
    public static StackTraceElement getCallerOfConstructor(final Class clazz) {
        return getCallerOfConstructor(clazz, new Pattern[0]);
    }

    /**
     * Gets the caller of a constructor.
     *
     * @param clazz the clazz
     * @param excluded the excluded
     * @return the caller of constructor
     */
    public static StackTraceElement getCallerOfConstructor(final Class clazz, final Pattern...excluded) {
        try {
            return getCallerOf(clazz, "", excluded);
        } catch (NotFoundException nfe) {
            log.debug("Looking for adviced init method because of {}", nfe.getMessage());
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            for (int i = 1; i < stackTrace.length; i++) {
                if (stackTrace[i].getMethodName().startsWith("init$")) {
                    for (i++; i < stackTrace.length; i++) {
                        if (!matches(stackTrace[i].getMethodName(), excluded)) {
                            return stackTrace[i];
                        }
                    }
                }
            }
            throw new NotFoundException("new " + clazz.getSimpleName() + "(..) not part of " + stackTrace);
        }
    }

    /**
     * Gets the caller of the given signature.
     *
     * @param signature the signature
     * @return the caller of
     */
    public static StackTraceElement getCallerOf(final Signature signature) {
        return getCallerOf(signature, new Pattern[0]);
    }

    /**
     * Gets the caller of the given method.
     *
     * @param clazz the clazz
     * @param method the method
     * @return the caller of
     */
    public static StackTraceElement getCallerOf(final Class clazz, final Method method) {
        return getCallerOf(clazz, method, new Pattern[0]);
    }

    /**
     * Gets the caller of the given method.
     *
     * @param clazz the clazz
     * @param methodName the method name
     * @return the caller of
     */
    public static StackTraceElement getCallerOf(final Class clazz, final String methodName) {
        return getCallerOf(clazz, methodName, new Pattern[0]);
    }

    /**
     * Gets the caller of the given method.
     *
     * @param classname the classname
     * @param methodName the method name
     * @return the caller of
     */
    public static StackTraceElement getCallerOf(final String classname, final String methodName) {
        return getCallerOf(classname, methodName, new Pattern[0]);
    }

    /**
     * Gets the caller of the given signature.
     *
     * @param signature the signature
     * @param excluded the excluded
     * @return the caller of
     */
    public static StackTraceElement getCallerOf(final Signature signature, final Pattern... excluded) {
        if (signature instanceof MethodSignature) {
            return getCallerOf((MethodSignature) signature, excluded);
        } else if (signature instanceof ConstructorSignature) {
            return getCallerOf((ConstructorSignature) signature, excluded);
        } else {
            throw new IllegalArgumentException(signature + " is not a method or ctor signature");
        }
    }

    private static StackTraceElement getCallerOf(final ConstructorSignature signature,
            final Pattern... excluded) {
        return getCallerOfConstructor(signature.getDeclaringType(), excluded);
    }

    private static StackTraceElement getCallerOf(final MethodSignature signature,
            final Pattern... excluded) {
        return getCallerOf(signature.getDeclaringType(), signature.getMethod(), excluded);
    }

    /**
     * Gets the caller of the given method.
     *
     * @param clazz the clazz
     * @param method the method
     * @param excluded a list of filters which should be not considered as
     *        caller
     * @return the caller of
     */
    public static StackTraceElement getCallerOf(final Class clazz, final Method method, final Pattern... excluded) {
        return getCallerOf(clazz.getName(), method.getName(), excluded);
    }

    /**
     * Gets the caller of the given method.
     *
     * @param clazz the clazz
     * @param methodName the method name
     * @param excluded a list of filters which should be not considered as
     * caller
     * @return the caller of
     */
    public static StackTraceElement getCallerOf(final Class clazz, final String methodName, final Pattern... excluded) {
        return getCallerOf(clazz.getName(), methodName, excluded);
    }

    /**
     * Gets the caller of the given method.
     *
     * @param classname the classname
     * @param methodName the method name
     * @param excluded a list of filters which should be not considered as
     *        caller
     * @return the caller of
     */
    public static StackTraceElement getCallerOf(final String classname, final String methodName, final Pattern... excluded) {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (int i = getIndexOf(classname, methodName, stackTrace) + 1; i < stackTrace.length; i++) {
            if (!matches(stackTrace[i].getMethodName(), excluded)) {
                return stackTrace[i];
            }
        }
        throw new NotFoundException(classname + "." + methodName +"()");
    }

    private static int getIndexOf(final String classname, final String methodName,
            final StackTraceElement[] stackTrace) {
        for (int i = 1; i < stackTrace.length; i++) {
            StackTraceElement element = stackTrace[i];
            if (methodName.equals(element.getMethodName())
                    && classname.equals(element.getClassName())) {
                return i;
            }
        }
        throw new NotFoundException(classname + "." + methodName +"()");
    }

    private static boolean matches(final String methodName, final Pattern... excluded) {
        for (int j = 0; j < excluded.length; j++) {
            if (excluded[j].matcher(methodName).matches()) {
                return true;
            }
        }
        return false;
    }

    private static boolean matches(final String className, final Class... excluded) {
        for (int j = 0; j < excluded.length; j++) {
            if (className.equals(excluded[j].getName())) {
                return true;
            }
        }
        return false;
    }

    /**
     * Gets the caller class by examing the stacktrace.
     *
     * @return the caller class
     */
    public static Class getCallerClass() {
        return getCallerClass(new Pattern[0]);
    }

    /**
     * Gets the caller class by examing the stacktrace.
     *
     * @param excluded a list of filters which should be not considered as
     *        caller
     * @return the caller of
     */
    public static Class getCallerClass(final Pattern... excluded) {
        return getCallerClass(excluded, new Class[0]);
    }

    /**
     * Gets the caller class by examing the stacktrace.
     *
     * @param excludedMethods the excluded methods
     * @param excludedClasses the excluded classes
     * @return the caller class
     */
    public static Class getCallerClass(final Pattern[] excludedMethods, final Class...excludedClasses) {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        int i = 2;
        String scannerClassName = StackTraceScanner.class.getName();
        for (; i < stackTrace.length-1; i++) {
            if (!scannerClassName.equals(stackTrace[i].getClassName())) {
                break;
            }
        }
        for (; i < stackTrace.length-1; i++) {
            if (!matches(stackTrace[i].getMethodName(), excludedMethods)
                    && !matches(stackTrace[i].getClassName(), excludedClasses)) {
                break;
            }
        }
        String classname = stackTrace[i].getClassName();
        try {
            return Class.forName(classname);
        } catch (ClassNotFoundException ex) {
            throw new NotFoundException(classname, ex);
        }
    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy