/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 Hans Harz, Andrew Rustleund, IBM Corporation. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     James Sutherland - initial impl
//     05/14/2010-2.1 Guy Pelletier
//       - 253083: Add support for dynamic persistence using ORM.xml/eclipselink-orm.xml
//     Hans Harz, Andrew Rustleund - Bug 324862 - IndexOutOfBoundsException in
//           DatabaseSessionImpl.initializeDescriptors because @MapKey Annotation is not found.
//     04/21/2011-2.3 dclarke: Upgraded to support ASM 3.3.1
//     08/10/2011-2.3 Lloyd Fernandes : Bug 336133 - Validation error during processing on parameterized generic OneToMany Entity relationship from MappedSuperclass
//     10/05/2012-2.4.1 Guy Pelletier
//       - 373092: Exceptions using generics, embedded key and entity inheritance
//     19/04/2014-2.6 Lukas Jungmann
//       - 429992: JavaSE 8/ASM 5.0.1 support (EclipseLink silently ignores Entity classes with lambda expressions)
//     11/05/2015-2.6 Dalia Abo Sheasha
//       - 480787 : Wrap several privileged method calls with a doPrivileged block
package org.eclipse.persistence.internal.jpa.metadata.accessors.objects;

import java.io.IOException;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.jpa.metadata.MetadataDescriptor;
import org.eclipse.persistence.internal.jpa.metadata.MetadataLogger;
import org.eclipse.persistence.internal.libraries.asm.AnnotationVisitor;
import org.eclipse.persistence.internal.libraries.asm.EclipseLinkAnnotationVisitor;
import org.eclipse.persistence.internal.libraries.asm.Attribute;
import org.eclipse.persistence.internal.libraries.asm.ClassReader;
import org.eclipse.persistence.internal.libraries.asm.EclipseLinkClassVisitor;
import org.eclipse.persistence.internal.libraries.asm.EclipseLinkFieldVisitor;
import org.eclipse.persistence.internal.libraries.asm.EclipseLinkClassReader;
import org.eclipse.persistence.internal.libraries.asm.FieldVisitor;
import org.eclipse.persistence.internal.libraries.asm.EclipseLinkMethodVisitor;
import org.eclipse.persistence.internal.libraries.asm.MethodVisitor;
import org.eclipse.persistence.internal.libraries.asm.Type;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.logging.SessionLogEntry;

/**
 * INTERNAL: A metadata factory that uses ASM technology and no reflection
 * whatsoever to process the metadata model.
 *
 * @author James Sutherland
 * @since EclipseLink 1.2
 */
public class MetadataAsmFactory extends MetadataFactory {
    /** Set of primitive type codes. */
    public static final String PRIMITIVES = "VJIBZCSFD";
    /** Set of desc token characters. */
    public static final String TOKENS = "()<>;";

    /**
     * INTERNAL:
     */
    public MetadataAsmFactory(MetadataLogger logger, ClassLoader loader) {
        super(logger, loader);

        addMetadataClass("I", new MetadataClass(this, int.class));
        addMetadataClass("J", new MetadataClass(this, long.class));
        addMetadataClass("S", new MetadataClass(this, short.class));
        addMetadataClass("Z", new MetadataClass(this, boolean.class));
        addMetadataClass("F", new MetadataClass(this, float.class));
        addMetadataClass("D", new MetadataClass(this, double.class));
        addMetadataClass("C", new MetadataClass(this, char.class));
        addMetadataClass("B", new MetadataClass(this, byte.class));
    }

    /**
     * Build the class metadata for the class name using ASM to read the class
     * byte codes.
     */
    protected void buildClassMetadata(MetadataClass metadataClass, String className, boolean isLazy) {
        ClassMetadataVisitor visitor = new ClassMetadataVisitor(metadataClass, isLazy);
        InputStream stream = null;
        try {
            String resourceString = className.replace('.', '/') + ".class";
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                final String f_resourceString = resourceString;
                stream = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
                    @Override
                    public InputStream run() {
                        return m_loader.getResourceAsStream(f_resourceString);
                    }
                });
            } else {
                stream = m_loader.getResourceAsStream(resourceString);
            }

            ClassReader reader = new ClassReader(stream);
            Attribute[] attributes = new Attribute[0];
            reader.accept(visitor, attributes, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
        } catch (IllegalArgumentException iae) {
            // class was probably compiled with some newer than officially
            // supported and tested JDK
            // in such case log a warning and try to re-read the class
            // without class version check
            SessionLog log = getLogger().getSession() != null
                    ? getLogger().getSession().getSessionLog() : AbstractSessionLog.getLog();
            if (log.shouldLog(SessionLog.WARNING, SessionLog.METADATA)) {
                SessionLogEntry entry = new SessionLogEntry(getLogger().getSession(), SessionLog.WARNING, SessionLog.METADATA, iae);
                entry.setMessage(ExceptionLocalization.buildMessage("unsupported_classfile_version", new Object[] { className }));
                log.log(entry);
            }
            if (stream != null) {
                try {
                    ClassReader reader = new EclipseLinkClassReader(stream);
                    Attribute[] attributes = new Attribute[0];
                    reader.accept(visitor, attributes, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
                } catch (Exception e) {
                    // our fall-back failed, this is severe
                    if (log.shouldLog(SessionLog.SEVERE, SessionLog.METADATA)) {
                        SessionLogEntry entry = new SessionLogEntry(getLogger().getSession(), SessionLog.SEVERE, SessionLog.METADATA, e);
                        entry.setMessage(ExceptionLocalization.buildMessage("unsupported_classfile_version", new Object[] { className }));
                        log.log(entry);
                    }
                    addMetadataClass(getVirtualMetadataClass(className));
                }
            } else {
                addMetadataClass(getVirtualMetadataClass(className));
            }
        } catch (Exception exception) {
            SessionLog log = getLogger().getSession() != null
                    ? getLogger().getSession().getSessionLog() : AbstractSessionLog.getLog();
            if (log.shouldLog(SessionLog.FINEST, SessionLog.METADATA)) {
                log.logThrowable(SessionLog.FINEST, SessionLog.METADATA, exception);
            }
            addMetadataClass(getVirtualMetadataClass(className));
        } finally {
            try {
                if (stream != null) {
                    stream.close();
                }
            } catch (IOException ignore) {
                // Ignore.
            }
        }
    }

    /**
     * Return the class metadata for the class name.
     */
    @Override
    public MetadataClass getMetadataClass(String className) {
        return getMetadataClass(className, false);
    }

    /**
     * Return the class metadata for the class name.
     */
    @Override
    public MetadataClass getMetadataClass(String className, boolean isLazy) {
        if (className == null) {
            return null;
        }

        MetadataClass metaClass = m_metadataClasses.get(className);
        if ((metaClass == null) || (!isLazy && metaClass.isLazy())) {
            if (metaClass != null) {
                metaClass.setIsLazy(false);
            }
            buildClassMetadata(metaClass, className, isLazy);
            metaClass = m_metadataClasses.get(className);
        }

        return metaClass;
    }

    /**
     * INTERNAL: This method resolves generic types based on the ASM class
     * metadata. Unless every other factory (e.g. APT mirror factory) respects
     * the generic format as built from ASM this method will not work since it
     * is very tied to it.
     */
    @Override
    public void resolveGenericTypes(MetadataClass child, List<String> genericTypes, MetadataClass parent, MetadataDescriptor descriptor) {
        // If we have a generic parent we need to grab our generic types
        // that may be used (and therefore need to be resolved) to map
        // accessors correctly.
        if (genericTypes != null) {
            // The generic types provided map to its parents generic types. The
            // generics also include the superclass, and interfaces. The parent
            // generics include the type and ":" and class.

            List<String> parentGenericTypes = parent.getGenericType();
            if (parentGenericTypes != null) {
                List<String> genericParentTemp = new ArrayList<>(genericTypes);
                genericParentTemp.removeAll(child.getInterfaces());

                int size = genericParentTemp.size();
                int parentIndex = 0;

                for (int index = genericTypes.indexOf(parent.getName()) + 1; index < size; index++) {
                    String actualTypeArgument = genericTypes.get(index);
                    // Ignore extra types on the end of the child, such as
                    // interface generics.
                    if (parentIndex >= parentGenericTypes.size()) {
                        break;
                    }
                    String variable = parentGenericTypes.get(parentIndex);

                    // if we get as far as the superclass name in the parent generic type list,
                    // there is nothing more to process.  We have processed all the generics in the type definition
                    if (variable.equals(parent.getSuperclassName())){
                        break;
                    }
                    parentIndex = parentIndex + 3;

                    // We are building bottom up and need to link up any
                    // TypeVariables with the actual class from the originating
                    // entity.
                    if (actualTypeArgument.length() == 1) {
                        index++;
                        actualTypeArgument = genericTypes.get(index);
                        descriptor.addGenericType(variable, descriptor.getGenericType(actualTypeArgument));
                    } else {
                        descriptor.addGenericType(variable, actualTypeArgument);
                    }
                }
            }
        }
    }

    /**
     * Walk the class byte codes and collect the class info.
     */
    public class ClassMetadataVisitor extends EclipseLinkClassVisitor {

        private boolean isLazy;
        private boolean processedMemeber;
        private MetadataClass classMetadata;

        ClassMetadataVisitor(MetadataClass metadataClass, boolean isLazy) {
            super();
            this.isLazy = isLazy;
            this.classMetadata = metadataClass;
        }

        @Override
        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            String className = toClassName(name);
            if ((this.classMetadata == null) || !this.classMetadata.getName().equals(className)) {
                this.classMetadata = new MetadataClass(MetadataAsmFactory.this, className, isLazy);
                addMetadataClass(this.classMetadata);
            }
            this.classMetadata.setName(className);
            this.classMetadata.setSuperclassName(toClassName(superName));
            this.classMetadata.setModifiers(access);
            this.classMetadata.setGenericType(processDescription(signature, true));

            for (String interfaceName : interfaces) {
                this.classMetadata.addInterface(toClassName(interfaceName));
            }
        }

        @Override
        public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
            this.processedMemeber = true;
            if (this.classMetadata.isLazy()) {
                return null;
            }
            return new MetadataFieldVisitor(this.classMetadata, access, name, desc, signature, value);
        }

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            this.processedMemeber = true;
            if (this.classMetadata.isLazy() || name.indexOf("init>") != -1) {
                return null;
            }
            return new MetadataMethodVisitor(this.classMetadata, access, name, signature, desc, exceptions);
        }

        @Override
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
            boolean isJPA = false;
            if (desc.startsWith("Lkotlin")) {
                //ignore kotlin annotations
                return null;
            }
            if (desc.startsWith("Ljava")) {
                char c = desc.charAt(5);
                //ignore annotations from 'java' namespace
                if (c == '/') {
                    return null;
                }
                //ignore annotations from other then 'javax/persistence' namespace
                if (desc.regionMatches(5, "x/", 0, 2)) {
                    if (desc.regionMatches(7, "persistence", 0, "persistence".length())) {
                        isJPA = true;
                    } else {
                        return null;
                    }
                }
            }
            if (desc.startsWith("Ljakarta")) {
                //ignore annotations from other then 'jakarta/persistence' namespace
                    if (desc.regionMatches(9, "persistence", 0, "persistence".length())) {
                        isJPA = true;
                    } else {
                        return null;
                    }
            }
            if (!this.processedMemeber && this.classMetadata.isLazy()) {
                this.classMetadata.setIsLazy(false);
            }
            //this currently forbids us to use meta-annotations defined in EclipseLink packages
            return new MetadataAnnotationVisitor(this.classMetadata, desc, isJPA || desc.startsWith("Lorg/eclipse/persistence"));
        }

    }

    /**
     * {@link AnnotationVisitor} used to process class, field , and method
     * annotations populating a {@link MetadataAnnotation} and its nested state.
     *
     * @see MetadataAnnotationArrayVisitor for population of array attributes
     */
    class MetadataAnnotationVisitor extends EclipseLinkAnnotationVisitor {

        /**
         * Element the annotation is being applied to. If this is null the
         * {@link MetadataAnnotation} being constructed is a nested annotation
         * and is already referenced from its parent.
         */
        private MetadataAnnotatedElement element;

        /**
         * {@link MetadataAnnotation} being populated
         */
        private MetadataAnnotation annotation;

        MetadataAnnotationVisitor(MetadataAnnotatedElement element, String name) {
            this(element, name, true);
        }

        MetadataAnnotationVisitor(MetadataAnnotatedElement element, String name, boolean isRegular) {
            super();
            this.element = element;
            this.annotation = new MetadataAnnotation();
            this.annotation.setName(processDescription(name, false).get(0));
            this.annotation.setIsMeta(!isRegular);
        }

        public MetadataAnnotationVisitor(MetadataAnnotation annotation) {
            super();
            this.annotation = annotation;
        }

        @Override
        public void visit(String name, Object value) {
            this.annotation.addAttribute(name, annotationValue(null, value));
        }

        @Override
        public void visitEnum(String name, String desc, String value) {
            this.annotation.addAttribute(name, annotationValue(desc, value));
        }

        @Override
        public AnnotationVisitor visitAnnotation(String name, String desc) {
            MetadataAnnotation mda = new MetadataAnnotation();
            mda.setName(processDescription(desc, false).get(0));
            this.annotation.addAttribute(name, mda);
            return new MetadataAnnotationVisitor(mda);
        }

        @Override
        public AnnotationVisitor visitArray(String name) {
            return new MetadataAnnotationArrayVisitor(this.annotation, name);
        }

        @Override
        public void visitEnd() {
            if (this.element != null) {
                if (this.annotation.isMeta()) {
                    this.element.addMetaAnnotation(this.annotation);
                } else {
                    this.element.addAnnotation(this.annotation);
                }
            }
        }
    }

    /**
     * Specialized visitor to handle the population of arrays of annotation
     * values.
     */
    class MetadataAnnotationArrayVisitor extends EclipseLinkAnnotationVisitor {

        private MetadataAnnotation annotation;

        private String attributeName;

        private List<Object> values;

        public MetadataAnnotationArrayVisitor(MetadataAnnotation annotation, String name) {
            super();
            this.annotation = annotation;
            this.attributeName = name;
            this.values = new ArrayList<Object>();
        }

        @Override
        public void visit(String name, Object value) {
            this.values.add(annotationValue(null, value));
        }

        @Override
        public void visitEnum(String name, String desc, String value) {
            this.values.add(annotationValue(desc, value));
        }

        @Override
        public AnnotationVisitor visitAnnotation(String name, String desc) {
            MetadataAnnotation mda = new MetadataAnnotation();
            mda.setName(processDescription(desc, false).get(0));
            this.values.add(mda);
            return new MetadataAnnotationVisitor(mda);
        }

        @Override
        public void visitEnd() {
            this.annotation.addAttribute(this.attributeName, this.values.toArray());
        }
    }

    /**
     * Factory for the creation of {@link MetadataField} handling basic type,
     * generics, and annotations.
     */
    class MetadataFieldVisitor extends EclipseLinkFieldVisitor {

        private MetadataField field;

        public MetadataFieldVisitor(MetadataClass classMetadata, int access, String name, String desc, String signature, Object value) {
            super();
            this.field = new MetadataField(classMetadata);
            this.field.setModifiers(access);
            this.field.setName(name);
            this.field.setAttributeName(name);
            this.field.setGenericType(processDescription(signature, true));
            this.field.setType(processDescription(desc, false).get(0));
        }

        @Override
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
            if (desc.startsWith("Ljavax/persistence") || desc.startsWith("Ljakarta/persistence")
                    || desc.startsWith("Lorg/eclipse/persistence")) {
                return new MetadataAnnotationVisitor(this.field, desc);
            }
            return null;
        }

        @Override
        public void visitEnd() {
            this.field.getDeclaringClass().addField(this.field);
        }
    }

    /**
     * Factory for the creation of {@link MetadataMethod} handling basic type,
     * generics, and annotations.
     */
    // Note: Subclassed EmptyListener to minimize signature requirements for
    // ignored MethodVisitor API
    class MetadataMethodVisitor extends EclipseLinkMethodVisitor {

        private MetadataMethod method;

        public MetadataMethodVisitor(MetadataClass classMetadata, int access, String name, String desc, String signature, String[] exceptions) {
            super();
            this.method = new MetadataMethod(MetadataAsmFactory.this, classMetadata);

            this.method.setName(name);
            this.method.setAttributeName(Helper.getAttributeNameFromMethodName(name));
            this.method.setModifiers(access);

            this.method.setGenericType(processDescription(desc, true));

            List<String> argumentNames = processDescription(signature, false);
            if (argumentNames != null && !argumentNames.isEmpty()) {
                this.method.setReturnType(argumentNames.get(argumentNames.size() - 1));
                argumentNames.remove(argumentNames.size() - 1);
                this.method.setParameters(argumentNames);
            }
        }

        @Override
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
            if (desc.startsWith("Ljavax/persistence") || desc.startsWith("Ljakarta/persistence")
                    || desc.startsWith("Lorg/eclipse/persistence")) {
                return new MetadataAnnotationVisitor(this.method, desc);
            }
            return null;
        }

        /**
         * At the end of visiting this method add it to the
         * {@link MetadataClass} and handle duplicate method names by chaining
         * them.
         */
        @Override
        public void visitEnd() {
            MetadataClass classMetadata = this.method.getMetadataClass();

            MetadataMethod existing = classMetadata.getMethods().get(this.method.getName());
            if (existing == null) {
                classMetadata.getMethods().put(this.method.getName(), this.method);
            } else {
                // Handle methods with the same name.
                while (existing.getNext() != null) {
                    existing = existing.getNext();
                }
                existing.setNext(this.method);
            }
        }

    }

    /**
     * Get MetadataClass for a class which can not be found
     * @param className class which has not been found
     * @return MetadataClass
     */
    private MetadataClass getVirtualMetadataClass(String className) {
        // Some basic types can't be found, so can just be registered
        // (i.e. arrays). Also, VIRTUAL classes may also not exist,
        // therefore, tag the MetadataClass as loadable false. This will be
        // used to determine if a class will be dynamically created or not.
        MetadataClass metadataClass = new MetadataClass(this, className, false);
        // If the class is a JDK class, then maybe there is a class loader
        // issues,
        // since it is a JDK class, just use reflection.
        if ((className.length() > 5) && className.substring(0, 5).equals("java.")) {
            try {
                Class<?> reflectClass = Class.forName(className);
                if (reflectClass.getSuperclass() != null) {
                    metadataClass.setSuperclassName(reflectClass.getSuperclass().getName());
                }
                for (Class reflectInterface : reflectClass.getInterfaces()) {
                    metadataClass.addInterface(reflectInterface.getName());
                }
            } catch (Exception failed) {
                SessionLog log = getLogger().getSession() != null
                        ? getLogger().getSession().getSessionLog() : AbstractSessionLog.getLog();
                if (log.shouldLog(SessionLog.FINE, SessionLog.METADATA)) {
                    log.logThrowable(SessionLog.FINE, SessionLog.METADATA, failed);
                }
                metadataClass.setIsAccessible(false);
            }
        } else {
            metadataClass.setIsAccessible(false);
        }
        return metadataClass;
    }

    /**
     * Process the byte-code argument description and return the array of Java
     * class names. i.e.
     * "(Lorg/foo/Bar;Z)Ljava/lang/Boolean;"={@literal >}[org.foo.Bar,boolean
     * ,java.lang.Boolean]
     */
    private static List<String> processDescription(String desc, boolean isGeneric) {
        if (desc == null) {
            return null;
        }
        List<String> arguments = new ArrayList<String>();
        int index = 0;
        int length = desc.length();
        boolean isGenericTyped=false;
        // PERF: Use char array to make char index faster (note this is a heavily optimized method, be very careful on changes)
        char[] chars = desc.toCharArray();
        while (index < length) {
            char next = chars[index];
            if (('(' != next) && (')' != next) && ('<' != next) && ('>' != next) && (';' != next)) {
                if (next == 'L') {
                    index++;
                    int start = index;
                    next = chars[index];
                    while (('(' != next) && (')' != next) && ('<' != next) && ('>' != next) && (';' != next)) {
                        index++;
                        next = chars[index];
                    }
                    arguments.add(toClassName(desc.substring(start, index)));
                    if(isGenericTyped) {
                        isGenericTyped=false;
                        if(next == '<') {
                            int cnt = 1;
                            while((cnt > 0) && (++index<desc.length())) {
                               switch (desc.charAt(index)) {
                                    case '<': cnt ++; break;
                                    case '>': cnt --; break;
                               }
                            }
                         }
                     }
                } else if (!isGeneric && (PRIMITIVES.indexOf(next) != -1)) {
                    // Primitives.
                    arguments.add(getPrimitiveName(next));
                } else if (next == '[') {
                    // Arrays.
                    int start = index;
                    index++;
                    next = chars[index];
                    // Nested arrays.
                    while (next == '[') {
                        index++;
                        next = chars[index];
                    }
                    if (PRIMITIVES.indexOf(next) == -1) {
                        while (next != ';') {
                            index++;
                            next = chars[index];
                        }
                        arguments.add(toClassName(desc.substring(start, index + 1)));
                    } else {
                        arguments.add(desc.substring(start, index + 1));
                    }
                } else {
                    // Is a generic type variable.
                    int start = index;
                    int end = start;

                    char myNext = next;

                    while (':' != myNext && '(' != myNext && ')' != myNext && '<' != myNext && '>' != myNext && ';' != myNext && end < length - 1) {
                        end++;
                        myNext = chars[end];
                    }

                    if (myNext == ':') {
                        arguments.add(desc.substring(start, end));
                        isGenericTyped=true;
                        index = end;
                        arguments.add(":");
                        if(desc.charAt(index+1)==':') {
                            index ++;
                        }
                    } else if (myNext == ';' && next == 'T') {
                        arguments.add(new String(new char[] { next }));
                        arguments.add(desc.substring(start + 1, end));
                        index = end - 1;
                    } else {
                        arguments.add(new String(new char[] { next }));
                    }
                }
            }
            index++;
        }
        return arguments;

    }

    /**
     * Return the Java type name for the primitive code.
     */
    private static String getPrimitiveName(char primitive) {
        if (primitive == 'V') {
            return "void";
        } else if (primitive == 'I') {
            return "int";
        } else if (primitive == 'Z') {
            return "boolean";
        } else if (primitive == 'J') {
            return "long";
        } else if (primitive == 'F') {
            return "float";
        } else if (primitive == 'D') {
            return "double";
        } else if (primitive == 'B') {
            return "byte";
        } else if (primitive == 'C') {
            return "char";
        } else if (primitive == 'S') {
            return "short";
        } else {
            return new String(new char[] { primitive });
        }
    }

    private static String toClassName(String classDescription) {
        if (classDescription == null) {
            return "void";
        }
        return classDescription.replace('/', '.');
    }

    /**
     * Convert the annotation value into the value used in the meta model
     */
    private static Object annotationValue(String description, Object value) {
        if (value instanceof Type) {
            return ((Type) value).getClassName();
        }
        return value;
    }
}
