<commit_before>/*
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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 org.jboss.weld.util.reflection;

import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.enterprise.inject.spi.AnnotatedConstructor;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.InjectionPoint;

import org.jboss.classfilewriter.util.DescriptorUtils;
import org.jboss.weld.ejb.spi.BusinessInterfaceDescriptor;
import org.jboss.weld.resources.ClassLoaderResourceLoader;
import org.jboss.weld.resources.WeldClassLoaderResourceLoader;

/**
 * Utility class to produce friendly names e.g. for debugging
 *
 * @author <NAME>
 * @author <NAME>
 * @author <NAME>
 */
public class Formats {

    private static final String SNAPSHOT = "SNAPSHOT";
    private static final String NULL = "null";
    private static final String SQUARE_BRACKETS = "[]";

    private static final String BCEL_CLASS_PARSER_FQCN = "com.sun.org.apache.bcel.internal.classfile.ClassParser";
    private static final String BCEL_JAVA_CLASS_FQCN = "com.sun.org.apache.bcel.internal.classfile.JavaClass";
    private static final String BCEL_METHOD_FQCN = "com.sun.org.apache.bcel.internal.classfile.Method";
    private static final String BCEL_LINE_NUMBER_TABLE_FQCN = "com.sun.org.apache.bcel.internal.classfile.LineNumberTable";
    private static final String BCEL_M_PARSE = "parse";
    private static final String BCEL_M_GET_METHODS = "getMethods";
    private static final String BCEL_M_GET_LINE_NUMBER_TABLE = "getLineNumberTable";
    private static final String BCEL_M_GET_SOURCE_LINE = "getSourceLine";
    private static final String BCEL_M_GET_NAME = "getName";
    private static final String BCEL_M_GET_MODIFIERS = "getModifiers";
    private static final String BCEL_M_GET_SIGNATURE = "getSignature";

    private static final String INIT_METHOD_NAME = "<init>";

    private Formats() {
    }

    /**
     * See also WELD-1454.
     *
     * @param ij
     * @return the formatted string
     */
    public static String formatAsStackTraceElement(InjectionPoint ij) {
        Member member;
        if (ij.getAnnotated() instanceof AnnotatedField) {
            AnnotatedField<?> annotatedField = (AnnotatedField<?>) ij.getAnnotated();
            member = annotatedField.getJavaMember();
        } else if (ij.getAnnotated() instanceof AnnotatedParameter<?>) {
            AnnotatedParameter<?> annotatedParameter = (AnnotatedParameter<?>) ij.getAnnotated();
            member = annotatedParameter.getDeclaringCallable().getJavaMember();
        } else {
            // Not throwing an exception, because this method is invoked when an exception is already being thrown.
            // Throwing an exception here would hide the original exception.
            return "-";
        }
        return formatAsStackTraceElement(member);
    }

    public static String formatAsStackTraceElement(Member member) {
        return member.getDeclaringClass().getName()
            + "." + (member instanceof Constructor<?> ? INIT_METHOD_NAME : member.getName())
            + "(" + getFileName(member.getDeclaringClass()) + ":" + getLineNumber(member) + ")";
    }

    /**
     * Try to get the line number associated with the given member.
     *
     * The reflection API does not expose such an info and so we need to analyse the bytecode. Unfortunately, it seems there is no way to get this kind of
     * information for fields. Moreover, the <code>LineNumberTable</code> attribute is just optional, i.e. the compiler is not required to store this
     * information at all. See also <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.1">Java Virtual Machine Specification</a>
     *
     * Implementation note: it wouldn't be appropriate to add a bytecode scanning dependency just for this functionality, therefore Apache BCEL included in
     * Oracle JDK 1.5+ and OpenJDK 1.6+ is used. Other JVMs should not crash as we only use it if it's on the classpath and by means of reflection calls.
     *
     * @param member
     * @param resourceLoader
     * @return the line number or 0 if it's not possible to find it
     */
    public static int getLineNumber(Member member) {

        if (!(member instanceof Method || member instanceof Constructor)) {
            // We are not able to get this info for fields
            return 0;
        }

        if (!Reflections.isClassLoadable(BCEL_JAVA_CLASS_FQCN, WeldClassLoaderResourceLoader.INSTANCE)) {
            // Apache BCEL classes not on the classpath
            return 0;
        }

        String classFile = member.getDeclaringClass().getName().replace('.', '/');
        ClassLoaderResourceLoader classFileResourceLoader = new ClassLoaderResourceLoader(member.getDeclaringClass().getClassLoader());
        InputStream in = null;

        try {
            URL classFileUrl = classFileResourceLoader.getResource(classFile + ".class");

            if (classFileUrl == null) {
                // The class file is not available
                return 0;
            }
            in = classFileUrl.openStream();

            Class<?> classParserClass = Reflections.loadClass(BCEL_CLASS_PARSER_FQCN, WeldClassLoaderResourceLoader.INSTANCE);
            Class<?> javaClassClass = Reflections.loadClass(BCEL_JAVA_CLASS_FQCN, WeldClassLoaderResourceLoader.INSTANCE);
            Class<?> methodClass = Reflections.loadClass(BCEL_METHOD_FQCN, WeldClassLoaderResourceLoader.INSTANCE);
            Class<?> lntClass = Reflections.loadClass(BCEL_LINE_NUMBER_TABLE_FQCN, WeldClassLoaderResourceLoader.INSTANCE);

            Object parser = classParserClass.getConstructor(InputStream.class, String.class).newInstance(in, classFile);
            Object javaClass = classParserClass.getMethod(BCEL_M_PARSE).invoke(parser);

            // First get all declared methods and constructors
            // Note that in bytecode constructor is translated into a method
            Object[] methods = (Object[]) javaClassClass.getMethod(BCEL_M_GET_METHODS).invoke(javaClass);
            Object match = null;

            String signature;
            String name;
            if (member instanceof Method) {
                signature = DescriptorUtils.methodDescriptor((Method) member);
                name = member.getName();
            } else if (member instanceof Constructor) {
                signature = DescriptorUtils.makeDescriptor((Constructor<?>) member);
                name = INIT_METHOD_NAME;
            } else {
                return 0;
            }

            for (Object method : methods) {
                // Matching method must have the same name, modifiers and signature
                if (methodClass.getMethod(BCEL_M_GET_NAME).invoke(method).equals(name)
                        && methodClass.getMethod(BCEL_M_GET_MODIFIERS).invoke(method).equals(member.getModifiers())<commit_msg>WELD-1853 Also try DefaultResourceLoader to load BCEL classes<commit_after>/*
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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 org.jboss.weld.util.reflection;

import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.enterprise.inject.spi.AnnotatedConstructor;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.InjectionPoint;

import org.jboss.classfilewriter.util.DescriptorUtils;
import org.jboss.weld.ejb.spi.BusinessInterfaceDescriptor;
import org.jboss.weld.resources.ClassLoaderResourceLoader;
import org.jboss.weld.resources.DefaultResourceLoader;
import org.jboss.weld.resources.WeldClassLoaderResourceLoader;
import org.jboss.weld.resources.spi.ResourceLoader;

/**
 * Utility class to produce friendly names e.g. for debugging
 *
 * @author <NAME>
 * @author <NAME>
 * @author <NAME>
 */
public class Formats {

    private static final String SNAPSHOT = "SNAPSHOT";
    private static final String NULL = "null";
    private static final String SQUARE_BRACKETS = "[]";

    private static final String BCEL_CLASS_PARSER_FQCN = "com.sun.org.apache.bcel.internal.classfile.ClassParser";
    private static final String BCEL_JAVA_CLASS_FQCN = "com.sun.org.apache.bcel.internal.classfile.JavaClass";
    private static final String BCEL_METHOD_FQCN = "com.sun.org.apache.bcel.internal.classfile.Method";
    private static final String BCEL_LINE_NUMBER_TABLE_FQCN = "com.sun.org.apache.bcel.internal.classfile.LineNumberTable";
    private static final String BCEL_M_PARSE = "parse";
    private static final String BCEL_M_GET_METHODS = "getMethods";
    private static final String BCEL_M_GET_LINE_NUMBER_TABLE = "getLineNumberTable";
    private static final String BCEL_M_GET_SOURCE_LINE = "getSourceLine";
    private static final String BCEL_M_GET_NAME = "getName";
    private static final String BCEL_M_GET_MODIFIERS = "getModifiers";
    private static final String BCEL_M_GET_SIGNATURE = "getSignature";

    private static final String INIT_METHOD_NAME = "<init>";

    private Formats() {
    }

    /**
     * See also WELD-1454.
     *
     * @param ij
     * @return the formatted string
     */
    public static String formatAsStackTraceElement(InjectionPoint ij) {
        Member member;
        if (ij.getAnnotated() instanceof AnnotatedField) {
            AnnotatedField<?> annotatedField = (AnnotatedField<?>) ij.getAnnotated();
            member = annotatedField.getJavaMember();
        } else if (ij.getAnnotated() instanceof AnnotatedParameter<?>) {
            AnnotatedParameter<?> annotatedParameter = (AnnotatedParameter<?>) ij.getAnnotated();
            member = annotatedParameter.getDeclaringCallable().getJavaMember();
        } else {
            // Not throwing an exception, because this method is invoked when an exception is already being thrown.
            // Throwing an exception here would hide the original exception.
            return "-";
        }
        return formatAsStackTraceElement(member);
    }

    public static String formatAsStackTraceElement(Member member) {
        return member.getDeclaringClass().getName()
            + "." + (member instanceof Constructor<?> ? INIT_METHOD_NAME : member.getName())
            + "(" + getFileName(member.getDeclaringClass()) + ":" + getLineNumber(member) + ")";
    }

    /**
     * Try to get the line number associated with the given member.
     *
     * The reflection API does not expose such an info and so we need to analyse the bytecode. Unfortunately, it seems there is no way to get this kind of
     * information for fields. Moreover, the <code>LineNumberTable</code> attribute is just optional, i.e. the compiler is not required to store this
     * information at all. See also <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.1">Java Virtual Machine Specification</a>
     *
     * Implementation note: it wouldn't be appropriate to add a bytecode scanning dependency just for this functionality, therefore Apache BCEL included in
     * Oracle JDK 1.5+ and OpenJDK 1.6+ is used. Other JVMs should not crash as we only use it if it's on the classpath and by means of reflection calls.
     *
     * @param member
     * @param resourceLoader
     * @return the line number or 0 if it's not possible to find it
     */
    public static int getLineNumber(Member member) {

        if (!(member instanceof Method || member instanceof Constructor)) {
            // We are not able to get this info for fields
            return 0;
        }

        ResourceLoader bcelResourceLoader = WeldClassLoaderResourceLoader.INSTANCE;

        if (!Reflections.isClassLoadable(BCEL_JAVA_CLASS_FQCN, bcelResourceLoader)) {
            // Try TCCL as a fallback
            bcelResourceLoader = DefaultResourceLoader.INSTANCE;
            if (!Reflections.isClassLoadable(BCEL_JAVA_CLASS_FQCN, bcelResourceLoader)) {
                // Apache BCEL classes not found on the classpath
                return 0;
            }
        }

        String classFile = member.getDeclaringClass().getName().replace('.', '/');
        ClassLoaderResourceLoader classFileResourceLoader = new ClassLoaderResourceLoader(member.getDeclaringClass().getClassLoader());
        InputStream in = null;

        try {
            URL classFileUrl = classFileResourceLoader.getResource(classFile + ".class");

            if (classFileUrl == null) {
                // The class file is not available
                return 0;
            }
            in = classFileUrl.openStream();

            Class<?> classParserClass = Reflections.loadClass(BCEL_CLASS_PARSER_FQCN, bcelResourceLoader);
            Class<?> javaClassClass = Reflections.loadClass(BCEL_JAVA_CLASS_FQCN, bcelResourceLoader);
            Class<?> methodClass = Reflections.loadClass(BCEL_METHOD_FQCN, bcelResourceLoader);
            Class<?> lntClass = Reflections.loadClass(BCEL_LINE_NUMBER_TABLE_FQCN, bcelResourceLoader);

            Object parser = classParserClass.getConstructor(InputStream.class, String.class).newInstance(in, classFile);
            Object javaClass = classParserClass.getMethod(BCEL_M_PARSE).invoke(parser);

            // First get all declared methods and constructors
            // Note that in bytecode constructor is translated into a method
            Object[] methods = (Object[]) javaClassClass.getMethod(BCEL_M_GET_METHODS).invoke(javaClass);
            Object match = null;

            String signature;
            String name;
            if (member instanceof Method) {
                signature = DescriptorUtils.methodDescriptor((Method) member);
                name = member.getName();
            } else if (member instanceof Constructor) {
                signature = DescriptorUtils.makeDescriptor((Constructor<?>) member);
                name = INIT_METHOD_NAME;
            } else {
                return 0;
            }

            for (Object method : methods) {
                // Matching method must have the same name, modifiers and signature
                if (methodClass.getMethod(BCEL_M_GET_NAME).invoke(method).equals(name)
                        && methodClass.getMethod(BCEL_M_GET_MODIFIERS).invoke(method).equals(member.getModifiers())
{'fraction_non_alphanumeric': 0.08683120158529994, 'fraction_numerical': 0.0032426589803638984, 'mean_word_length': 3.207680646791309, 'pattern_counts': {'":': 2, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7588736', 'n_tokens_mistral': 4594, 'n_tokens_neox': 4430, 'n_words': 1300}