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

org.nuiton.jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJavaClass Maven / Gradle / Ivy

There is a newer version: 3.1.5
Show newest version
/*
 * #%L
 * JAXX :: Compiler
 * %%
 * Copyright (C) 2008 - 2020 Code Lutin, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */
package org.nuiton.jaxx.compiler.reflect.resolvers;

import com.google.common.collect.ImmutableSet;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nuiton.jaxx.compiler.reflect.ClassDescriptor;
import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper;
import org.nuiton.jaxx.compiler.reflect.ClassDescriptorResolver;
import org.nuiton.jaxx.compiler.reflect.FieldDescriptor;
import org.nuiton.jaxx.compiler.reflect.MethodDescriptor;
import org.nuiton.jaxx.runtime.JAXXObjectDescriptor;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
 * To obtain a class descriptor from a java source file.
 *
 * @author Tony Chemit - [email protected]
 * @since 2.0.2
 */
public class ClassDescriptorResolverFromJavaClass extends ClassDescriptorResolver {

    /**
     * Logger
     */
    private static final Logger log =
            LogManager.getLogger(ClassDescriptorResolverFromJavaClass.class);

    public ClassDescriptorResolverFromJavaClass() {
        super(ClassDescriptorHelper.ResolverType.JAVA_CLASS);
    }

    @Override
    public ClassDescriptor resolveDescriptor(String className,
                                             URL source) throws ClassNotFoundException {

        if (log.isDebugEnabled()) {
            log.debug("for source " + className);
        }

        Class javaClass =
                ClassDescriptorHelper.getClass(className, getClassLoader());

        String name = javaClass.getName();
        Package p = javaClass.getPackage();
        String packageName = p != null ? p.getName() : null;
        Class superclass = javaClass.getSuperclass();
        String superclassName = superclass != null ? superclass.getName() : null;
        Class[] interfaces = javaClass.getInterfaces();
        String[] interfaceNames = new String[interfaces.length];
        for (int i = 0; i < interfaces.length; i++) {
            interfaceNames[i] = interfaces[i].getName();
        }
        boolean isInterface = javaClass.isInterface();
        boolean isArray = javaClass.isArray();
        String componentTypeName = isArray ? javaClass.getComponentType().getName() : null;
        ClassLoader classLoader = javaClass.getClassLoader();
        Constructor[] javaConstructors = javaClass.getConstructors();
        MethodDescriptor[] constructors = new MethodDescriptor[javaConstructors.length];
        for (int i = 0; i < constructors.length; i++) {
            constructors[i] = ClassDescriptorHelper.createMethodDescriptor(
                    javaConstructors[i],
                    javaClass.getClassLoader()
            );
        }
        Method[] javaMethods = javaClass.getMethods();
        MethodDescriptor[] methods = new MethodDescriptor[javaMethods.length];
        for (int i = 0; i < methods.length; i++) {
            methods[i] = ClassDescriptorHelper.createMethodDescriptor(
                    javaMethods[i],
                    javaClass.getClassLoader()
            );
        }

        ImmutableSet.Builder fieldsBuilder = ImmutableSet.builder();
        ImmutableSet.Builder declaredFieldsBuilder = ImmutableSet.builder();

        Set> pathFromRoot = pathFromRoot(javaClass);
        for (Class aClass : pathFromRoot) {
            fieldsBuilder.addAll(Arrays.asList(aClass.getFields()));
            declaredFieldsBuilder.addAll(Arrays.asList(aClass.getDeclaredFields()));
        }
        ImmutableSet javaFields = fieldsBuilder.build();
        FieldDescriptor[] fields = new FieldDescriptor[javaFields.size()];
        int i = 0;
        for (Field javaField : javaFields) {
            fields[i++] = ClassDescriptorHelper.createFieldDescriptor(javaField, javaClass.getClassLoader());
        }
        ImmutableSet javaDeclaredFields = declaredFieldsBuilder.build();
        FieldDescriptor[] declaredFields = new FieldDescriptor[javaDeclaredFields.size()];
        i = 0;
        for (Field javaDeclaredField : javaDeclaredFields) {
            declaredFields[i++] = ClassDescriptorHelper.createFieldDescriptor(javaDeclaredField, javaClass.getClassLoader());
        }

        JAXXObjectDescriptor jaxxObjectDescriptor =
                ClassDescriptorHelper.getJAXXObjectDescriptor(javaClass);

        Map typeParameters = new LinkedHashMap<>();
        for (TypeVariable> typeParameter : javaClass.getTypeParameters()) {
            typeParameters.put(typeParameter.getName(), typeParameter.getBounds()[0].getTypeName());
        }
        return new JavaClassClassDescriptor(
                javaClass,
                typeParameters,
                name,
                packageName,
                superclassName,
                interfaceNames,
                isInterface,
                isArray,
                componentTypeName,
                jaxxObjectDescriptor,
                classLoader,
                constructors,
                methods,
                fields,
                declaredFields
        );
    }

    private Set> pathFromRoot(Class type) {
        List> result = new LinkedList<>();
        while (type != null && type != Object.class) {
            result.add(type);
            type = type.getSuperclass();
        }
        Collections.reverse(result);
        return new LinkedHashSet<>(result);
    }


    private class JavaClassClassDescriptor extends ClassDescriptor {

        private final Class javaClass;
        private final Map typeParameters;

        public JavaClassClassDescriptor(
                Class javaClass,
                Map typeParameters, String name,
                String packageName,
                String superclassName,
                String[] interfaceNames,
                boolean anInterface,
                boolean array,
                String componentTypeName,
                JAXXObjectDescriptor jaxxObjectDescriptor,
                ClassLoader classLoader,
                MethodDescriptor[] constructors,
                MethodDescriptor[] methods,
                FieldDescriptor[] fields,
                FieldDescriptor[] declaredFields
        ) {
            super(
                    ClassDescriptorResolverFromJavaClass.this.getResolverType(),
                    name,
                    packageName,
                    superclassName,
                    interfaceNames,
                    anInterface,
                    array,
                    componentTypeName,
                    jaxxObjectDescriptor,
                    classLoader,
                    constructors,
                    methods,
                    fields,
                    declaredFields
            );
            this.javaClass = javaClass;
            this.typeParameters = typeParameters;
        }

        @Override
        public Map getTypeParameters() {
            return typeParameters;
        }
//        @Override
//        public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException {
//            return ClassDescriptorHelper.createFieldDescriptor(javaClass.getDeclaredField(name),
//                                                               javaClass.getClassLoader()
//            );
//        }

        @Override
        public MethodDescriptor getDeclaredMethodDescriptor(String name,
                                                            ClassDescriptor... parameterTypes) throws NoSuchMethodException {
            try {
                Class[] parameterTypeClasses = new Class[parameterTypes.length];
                for (int i = 0; i < parameterTypes.length; i++) {
                    parameterTypeClasses[i] = Class.forName(parameterTypes[i].getName());
                }
                return ClassDescriptorHelper.createMethodDescriptor(javaClass.getDeclaredMethod(name, parameterTypeClasses), javaClass.getClassLoader());
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }

        public Optional tryToGetDeclaredMethodDescriptor(String name, ClassDescriptor... parameterTypes) {
            try {
                Class[] parameterTypeClasses = new Class[parameterTypes.length];
                for (int i = 0; i < parameterTypes.length; i++) {
                    parameterTypeClasses[i] = Class.forName(parameterTypes[i].getName());
                }
                return Optional.of(ClassDescriptorHelper.createMethodDescriptor(javaClass.getDeclaredMethod(name, parameterTypeClasses), javaClass.getClassLoader()));
            } catch (Exception e) {
                return Optional.empty();
            }
        }

    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy