From fb7e1c6bb1f3615b2442b971d16881a398393ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thiago=20Henrique=20H=C3=BCpner?= Date: Fri, 16 Jun 2023 00:27:26 -0300 Subject: [PATCH] Fixes #3335 - Improves the extension --- extension/annotationscan-classfile/pom.xml | 27 ---- .../ClassfileAnnotationScanInitializer.java | 119 +++++++++--------- .../src/main/java/module-info.java | 4 +- 3 files changed, 60 insertions(+), 90 deletions(-) diff --git a/extension/annotationscan-classfile/pom.xml b/extension/annotationscan-classfile/pom.xml index 14cad2422a..ba3cd81f0d 100644 --- a/extension/annotationscan-classfile/pom.xml +++ b/extension/annotationscan-classfile/pom.xml @@ -50,33 +50,6 @@ - - io.github.wiverson - jtoolprovider-plugin - - - package - - java-tool - - - jar - true - true - true - - --update - --warn-if-resolved=incubating - --do-not-resolve-by-default - --file - ${project.build.directory}/${project.build.finalName}.jar - - ${project.build.directory}/${project.build.finalName}.jar - - - - - diff --git a/extension/annotationscan-classfile/src/main/java/cloud/piranha/extension/annotationscan/classfile/ClassfileAnnotationScanInitializer.java b/extension/annotationscan-classfile/src/main/java/cloud/piranha/extension/annotationscan/classfile/ClassfileAnnotationScanInitializer.java index 20d4f46f51..2a684100f4 100644 --- a/extension/annotationscan-classfile/src/main/java/cloud/piranha/extension/annotationscan/classfile/ClassfileAnnotationScanInitializer.java +++ b/extension/annotationscan-classfile/src/main/java/cloud/piranha/extension/annotationscan/classfile/ClassfileAnnotationScanInitializer.java @@ -36,11 +36,6 @@ import jakarta.servlet.ServletContainerInitializer; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; -import jakarta.servlet.annotation.MultipartConfig; -import jakarta.servlet.annotation.ServletSecurity; -import jakarta.servlet.annotation.WebFilter; -import jakarta.servlet.annotation.WebListener; -import jakarta.servlet.annotation.WebServlet; import sun.reflect.ReflectionFactory; import java.io.IOException; @@ -77,23 +72,17 @@ public class ClassfileAnnotationScanInitializer implements ServletContainerIniti */ private static final Logger LOGGER = System.getLogger(ClassfileAnnotationScanInitializer.class.getName()); - /** - * Stores the knows annotation classes - */ - private static final List KNOWN_ANNOTATION_CLASSES = List.of(desc(WebServlet.class), - desc(WebListener.class), - desc(WebFilter.class), - desc(ServletSecurity.class), - desc(MultipartConfig.class)); - /** * Stores the knows annotation packages */ - private static final List KNOWN_ANNOTATION_PACKAGES = List.of("jakarta.ws.rs", "jakarta.websocket"); - - private static ClassDesc desc(Class clazz) { - return clazz.describeConstable().orElseThrow(); - } + private static final List KNOWN_ANNOTATION_PACKAGES = List.of( + "jakarta.servlet", + "jakarta.websocket", + "jakarta.ws.rs", + "jakarta.faces", + "jakarta.persistence", + "jakarta.annotation" + ); /** * On startup. @@ -112,8 +101,6 @@ public void onStartup(Set> classes, ServletContext servletContext) thro webApp.getManager().setAnnotationManager(annotationManager); } - final AnnotationManager annotationMgr = annotationManager; - ClassLoader classLoader = webApp.getClassLoader(); if (!(classLoader instanceof ResourceManagerClassLoader resourceManagerClassLoader)) { LOGGER.log(WARNING, "ResourceManagerClassLoader not installed. This scanner does not work"); @@ -123,11 +110,11 @@ public void onStartup(Set> classes, ServletContext servletContext) thro resourceManager .getAllLocations() .filter(e -> e.endsWith(".class") && !e.endsWith("module-info.class") && !e.startsWith("/META-INF/versions")) - .filter(resource -> classFileHasWebAnnotations(readResource(resource, resourceManager))) + .filter(resource -> classFileHasJakartaAnnotations(readResource(resource, resourceManager))) .map(e -> loadClass(classLoader, e)) - .flatMap(this::getWebAnnotations) + .flatMap(this::getJakartaAnnotations) .map(annotationInstance -> new InternalAnnotationScanAnnotationInfo<>(annotationInstance, annotationInstance.annotationType())) - .forEach(annotationMgr::addAnnotation); + .forEach(annotationManager::addAnnotation); } @@ -154,22 +141,18 @@ private Class loadClass(ClassLoader classLoader, String className) { * @param clazz the class. * @return the stream of web annotations. */ - private Stream getWebAnnotations(Class clazz) { + private Stream getJakartaAnnotations(Class clazz) { return stream(clazz.getAnnotations()) - .filter(this::isWebAnnotation); + .filter(this::isJakartaAnnotation); } - private boolean isWebAnnotation(Annotation clazz) { - return isWebAnnotation(clazz.annotationType().describeConstable().orElse(ConstantDescs.CD_Object)); + private boolean isJakartaAnnotation(Annotation clazz) { + return isJakartaAnnotation(clazz.annotationType().describeConstable().orElse(ConstantDescs.CD_Object)); } - private boolean isWebAnnotation(ClassDesc annotation) { - - if (KNOWN_ANNOTATION_CLASSES.stream().anyMatch(annotation::equals)) { - return true; - } - - return KNOWN_ANNOTATION_PACKAGES.stream().anyMatch(thePackage -> annotation.packageName().equals(thePackage)); + private boolean isJakartaAnnotation(ClassDesc annotation) { + return KNOWN_ANNOTATION_PACKAGES.stream() + .anyMatch(thePackage -> annotation.packageName().startsWith(thePackage)); } private byte[] readResource(String resourceName, ResourceManager resourceManager) { @@ -180,7 +163,7 @@ private byte[] readResource(String resourceName, ResourceManager resourceManager } } - private boolean classFileHasWebAnnotations(byte[] classFileBytes) { + private boolean classFileHasJakartaAnnotations(byte[] classFileBytes) { /* * Without reflection the code would be similar to: * {@snippet lang="java" @@ -204,7 +187,7 @@ private boolean classFileHasWebAnnotations(byte[] classFileBytes) { List annotations = (List) Holder.ANNOTATIONS.invokeExact(optionalAttribute.get()); for (Object annotation : annotations) { ClassDesc annotationDesc = (ClassDesc) Holder.CLASS_SYMBOL.invokeExact(annotation); - if (isWebAnnotation(annotationDesc)) { + if (isJakartaAnnotation(annotationDesc)) { return true; } } @@ -215,42 +198,56 @@ private boolean classFileHasWebAnnotations(byte[] classFileBytes) { } } -@SuppressWarnings("checkstyle:JavadocVariable") class Holder { - static final Class CLASS_FILE_CLASS; - static final Class CLASS_MODEL_CLASS; - static final Class ATTRIBUTE_MAPPER_CLASS; - static final Class ATTRIBUTES_CLASS; - static final Class ANNOTATION_CLASS; - static final Class CLASS_FILE_OPTIONS_ARRAY_CLASS; - static final Class RUNTIME_VISIBLE_ANNOTATIONS_ATTRIBUTE_CLASS; - + /** + * Stores the handle to Classfile.parse(byte[]) + */ static final MethodHandle PARSE; + /** + * Stores the handle to ClassModel.findAttribute(AttributeMapper) + */ static final MethodHandle FIND_ATTRIBUTE; + /** + * Stores the handle to RuntimeVisibleAnnotationsAttribute.annotations() + */ static final MethodHandle ANNOTATIONS; + /** + * Stores the handle to Annotation.classSymbol() + */ static final MethodHandle CLASS_SYMBOL; + /** + * Stores the RuntimeVisibleAnnotationsAttributeMapper + */ static final Object RUNTIME_VISIBLE_ANNOTATIONS_ATTRIBUTE_MAPPER; + + /** + * Stores the value of trusted lookup + */ private static final int TRUSTED = -1; static { try { - final MethodHandles.Lookup trustedLookup = getLookup(); + MethodHandles.Lookup trustedLookup = getLookup(); - CLASS_FILE_CLASS = trustedLookup.findClass("jdk.internal.classfile.Classfile"); - CLASS_MODEL_CLASS = trustedLookup.findClass("jdk.internal.classfile.ClassModel"); - ATTRIBUTE_MAPPER_CLASS = trustedLookup.findClass("jdk.internal.classfile.AttributeMapper"); - ATTRIBUTES_CLASS = trustedLookup.findClass("jdk.internal.classfile.Attributes"); - ANNOTATION_CLASS = trustedLookup.findClass("jdk.internal.classfile.Annotation"); - CLASS_FILE_OPTIONS_ARRAY_CLASS = trustedLookup.findClass("[Ljdk.internal.classfile.Classfile$Option;"); - RUNTIME_VISIBLE_ANNOTATIONS_ATTRIBUTE_CLASS = trustedLookup.findClass("jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute"); - RUNTIME_VISIBLE_ANNOTATIONS_ATTRIBUTE_MAPPER = trustedLookup.findStaticGetter(Holder.ATTRIBUTES_CLASS, "RUNTIME_VISIBLE_ANNOTATIONS", Holder.ATTRIBUTE_MAPPER_CLASS).invoke(); + Class classFileClass = trustedLookup.findClass("jdk.internal.classfile.Classfile"); + Class classModelClass = trustedLookup.findClass("jdk.internal.classfile.ClassModel"); + Class attributeMapperClass = trustedLookup.findClass("jdk.internal.classfile.AttributeMapper"); + Class attributesClass = trustedLookup.findClass("jdk.internal.classfile.Attributes"); + Class annotationClass = trustedLookup.findClass("jdk.internal.classfile.Annotation"); + Class classFileOptionsArrayClass = trustedLookup.findClass("[Ljdk.internal.classfile.Classfile$Option;"); + Class runtimeVisibleAnnotationsAttributeClass = trustedLookup.findClass("jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute"); - MethodHandle parse = trustedLookup.findStatic(Holder.CLASS_FILE_CLASS, "parse", methodType(Holder.CLASS_MODEL_CLASS, byte[].class, Holder.CLASS_FILE_OPTIONS_ARRAY_CLASS)); - Object classFileOptionsEmptyArray = MethodHandles.arrayConstructor(Holder.CLASS_FILE_OPTIONS_ARRAY_CLASS).invoke(0); - PARSE = MethodHandles.insertArguments(parse, 1, classFileOptionsEmptyArray).asType(methodType(Object.class, byte[].class)); - FIND_ATTRIBUTE = trustedLookup.findVirtual(CLASS_MODEL_CLASS, "findAttribute", methodType(Optional.class, ATTRIBUTE_MAPPER_CLASS)).asType(methodType(Optional.class, Object.class, Object.class)); - ANNOTATIONS = trustedLookup.findVirtual(Holder.RUNTIME_VISIBLE_ANNOTATIONS_ATTRIBUTE_CLASS, "annotations", methodType(List.class)).asType(methodType(List.class, Object.class)); - CLASS_SYMBOL = trustedLookup.findVirtual(ANNOTATION_CLASS, "classSymbol", methodType(ClassDesc.class)).asType(methodType(ClassDesc.class, Object.class)); + MethodHandle parse = trustedLookup.findStatic(classFileClass, "parse", methodType(classModelClass, byte[].class, classFileOptionsArrayClass)); + Object classFileOptionsEmptyArray = MethodHandles.arrayConstructor(classFileOptionsArrayClass).invoke(0); + PARSE = MethodHandles.insertArguments(parse, 1, classFileOptionsEmptyArray) + .asType(methodType(Object.class, byte[].class)); + FIND_ATTRIBUTE = trustedLookup.findVirtual(classModelClass, "findAttribute", methodType(Optional.class, attributeMapperClass)) + .asType(methodType(Optional.class, Object.class, Object.class)); + ANNOTATIONS = trustedLookup.findVirtual(runtimeVisibleAnnotationsAttributeClass, "annotations", methodType(List.class)) + .asType(methodType(List.class, Object.class)); + CLASS_SYMBOL = trustedLookup.findVirtual(annotationClass, "classSymbol", methodType(ClassDesc.class)) + .asType(methodType(ClassDesc.class, Object.class)); + RUNTIME_VISIBLE_ANNOTATIONS_ATTRIBUTE_MAPPER = trustedLookup.findStaticGetter(attributesClass, "RUNTIME_VISIBLE_ANNOTATIONS", attributeMapperClass).invoke(); } catch (Throwable e) { throw new ExceptionInInitializerError(e); } diff --git a/extension/annotationscan-classfile/src/main/java/module-info.java b/extension/annotationscan-classfile/src/main/java/module-info.java index 38f476dacc..a4bf3068b2 100644 --- a/extension/annotationscan-classfile/src/main/java/module-info.java +++ b/extension/annotationscan-classfile/src/main/java/module-info.java @@ -36,8 +36,8 @@ exports cloud.piranha.extension.annotationscan.classfile; opens cloud.piranha.extension.annotationscan.classfile; - exports cloud.piranha.extension.annotationscan.classfile.internal to cloud.piranha.micro.core; - opens cloud.piranha.extension.annotationscan.classfile.internal to cloud.piranha.micro.core; + exports cloud.piranha.extension.annotationscan.classfile.internal; + opens cloud.piranha.extension.annotationscan.classfile.internal; requires cloud.piranha.core.api; requires cloud.piranha.core.impl;