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

io.helidon.integrations.graal.mp.nativeimage.extension.JaxRsMethodAnalyzer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2021, 2023 Oracle and/or its affiliates.
 *
 * 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 io.helidon.integrations.graal.mp.nativeimage.extension;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import io.helidon.integrations.graal.nativeimage.extension.NativeUtil;

import io.github.classgraph.ClassInfo;
import io.github.classgraph.ClassInfoList;
import io.github.classgraph.ClassRefTypeSignature;
import io.github.classgraph.MethodInfo;
import io.github.classgraph.MethodInfoList;
import io.github.classgraph.MethodParameterInfo;
import io.github.classgraph.TypeArgument;
import io.github.classgraph.TypeSignature;

/*
 * Analyzes JAX-RS resource method signatures and returns all types to be added for reflection.
 */
class JaxRsMethodAnalyzer {
    /*
     what we ignore:
     - JsonObject and JsonArray - part of JSON-P handling, which works without reflection
     - Response - part of JAX-RS and works already
     - String - no need to add it
     - Map, List, Set - basic collection classes - we only care about the type parameter, not the collection itself
     */
    private static final Set IGNORED_TYPES = Set.of("jakarta.json.JsonObject",
                                                            "jakarta.json.JsonArray",
                                                            "jakarta.ws.rs.core.Response",
                                                            "java.lang.String",
                                                            Map.class.getName(),
                                                            List.class.getName(),
                                                            Set.class.getName());

    private static final String HTTP_METHOD_ANNOTATION = "jakarta.ws.rs.HttpMethod";

    private final Set classesToAdd = new HashSet<>();
    private final HelidonMpFeature.BeforeAnalysisContext context;
    private final NativeUtil nativeUtil;

    JaxRsMethodAnalyzer(HelidonMpFeature.BeforeAnalysisContext context,
                        NativeUtil nativeUtil) {
        this.context = context;
        this.nativeUtil = nativeUtil;
    }

    Set> find() {
        ClassInfoList classes = context.scan()
                .getClassesWithMethodAnnotation(HTTP_METHOD_ANNOTATION);

        for (ClassInfo aClass : classes) {
            MethodInfoList methods = aClass.getMethodInfo();
            for (MethodInfo method : methods) {
                if (method.hasAnnotation(HTTP_METHOD_ANNOTATION)) {
                    add(method.getTypeSignatureOrTypeDescriptor()
                                .getResultType());

                    MethodParameterInfo[] parameterInfo = method.getParameterInfo();
                    for (MethodParameterInfo param : parameterInfo) {
                        if (param.getAnnotationInfo().isEmpty()) {
                            add(param.getTypeSignatureOrTypeDescriptor());
                        }
                    }
                }
            }
        }
        Set result = Set.copyOf(classesToAdd);
        classesToAdd.clear();

        return result.stream()
                .map(nativeUtil.classMapper("jaxrs-result-or-param"))
                .filter(Objects::nonNull)
                .filter(nativeUtil.inclusionFilter("jaxrs-result-or-param"))
                .collect(Collectors.toSet());
    }

    void add(TypeSignature type) {
        if (type instanceof ClassRefTypeSignature) {
            ClassRefTypeSignature crts = (ClassRefTypeSignature) type;
            if (add(crts.getFullyQualifiedClassName())) {
                List typeArgs = crts.getTypeArguments();
                if (typeArgs != null && !typeArgs.isEmpty()) {
                    typeArgs.forEach(it -> add(it.getTypeSignature()));
                }
            }
        } else {
            add(type.toString());
        }
    }

    boolean add(String type) {
        if (!IGNORED_TYPES.contains(type)) {
            return classesToAdd.add(type);
        }
        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy