From 5ded8e84cc28adf0006b7319cf03669c10f51013 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Thu, 17 Jul 2025 16:36:20 -0600 Subject: [PATCH] remove old asm & AnnotationMetadataReader supporting classes; adopt Spring's SimpleMetadataReaderFactory instead - see https://github.com/spring-projects/spring-framework/wiki/MergedAnnotation-API-internals --- LICENSE | 29 - NOTICE | 9 - .../AbstractRecursiveAnnotationVisitor.java | 108 -- .../AnnotationAttributesReadingVisitor.java | 131 -- .../AnnotationMetadataReadingVisitor.java | 207 ---- .../AnnotationReadingVisitorUtils.java | 176 --- .../ClassMetadataReadingVisitor.java | 246 ---- .../MethodMetadataReadingVisitor.java | 176 --- .../RecursiveAnnotationArrayVisitor.java | 112 -- .../RecursiveAnnotationAttributesVisitor.java | 55 - .../asm/AnnotationMetadataReader.java | 142 --- .../grails/common/compiler/asm/Attribute.java | 258 ---- .../common/compiler/asm/ByteVector.java | 339 ------ .../common/compiler/asm/ClassReader.java | 1056 ----------------- .../grails/common/compiler/asm/Context.java | 146 --- .../grails/common/compiler/asm/TypePath.java | 196 --- .../src/main/resources/META-INF/LICENSE | 233 ---- .../src/main/resources/META-INF/NOTICE | 18 - .../boot/config/tools/ClassPathScanner.groovy | 6 +- .../AnnotationMetadataReaderFactory.java | 39 - .../gorm/utils/ClasspathEntityScanner.groovy | 3 +- licenses/LICENSE-asm.txt | 27 - 22 files changed, 6 insertions(+), 3706 deletions(-) delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java delete mode 100644 grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java delete mode 100644 grails-common/src/main/resources/META-INF/LICENSE delete mode 100644 grails-common/src/main/resources/META-INF/NOTICE delete mode 100644 grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java delete mode 100644 licenses/LICENSE-asm.txt diff --git a/LICENSE b/LICENSE index 06f77ceaab6..1e51fd6e2a0 100644 --- a/LICENSE +++ b/LICENSE @@ -203,20 +203,6 @@ -------------------------------------------------------------------------- -BSD License - -The following classes within this product: - - org.apache.grails.common.compiler.asm.Attribute - org.apache.grails.common.compiler.asm.ByteVector - org.apache.grails.common.compiler.asm.ClassReader - org.apache.grails.common.compiler.asm.Context - org.apache.grails.common.compiler.asm.TypePath - -See the LICENSE/licenses-asm.txt file for the ASM license terms. - --------------------------------------------------------------------------- - Public Domain The following classes within this product: @@ -250,21 +236,6 @@ See licenses/LICENSE-CDDL.txt for the full license terms. -------------------------------------------------------------------------- -This product includes the following files from Spring Framework 5.3, developed by Pivotal Software, Inc., licensed under the Apache License 2.0: - - grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java - grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java - grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java - grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java - grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java - grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java - grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java - grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java - -See the above Apache License 2.0 for the terms governing these files. - --------------------------------------------------------------------------- - This product includes software developed by the OpenSymphony Group (http://www.opensymphony.com/). It uses Sitemesh2, licensed under the OpenSymphony Software License, Version 1.1. diff --git a/NOTICE b/NOTICE index b78f70d549b..d5e4c5dbbf5 100644 --- a/NOTICE +++ b/NOTICE @@ -8,11 +8,6 @@ The Apache Software Foundation (http://www.apache.org/). Additional Licenses ------------------ -ASM Library -This product includes software from ASM Library, licensed under BSD License. -Copyright 2000-2011 INRIA, France Telecom. -See licenses/LICENSE-asm.txt for the full license terms. - Project Reactor This product includes software from Project Reactor, licensed under Apache License, Version 2.0. 2011-2014 Pivotal Software, Inc. @@ -23,9 +18,5 @@ The original XML Schemas for Java EE Deployment Descriptors: may be obtained from: http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html -This product includes software from Spring Framework 5.3, developed by Pivotal Software, Inc. -Copyright 2002-2020 the original author or authors. -See the LICENSE file for the Apache License 2.0 terms. - This product includes software developed by the OpenSymphony Group (http://www.opensymphony.com/). It uses Sitemesh2, licensed under the OpenSymphony Software License, Version 1.1. See licenses/LICENSE-opensymphony.txt for the full license terms. \ No newline at end of file diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java deleted file mode 100644 index a810868fd4f..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * 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 - * - * https://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.apache.grails.common.annotation; - -import java.lang.reflect.Field; -import java.security.AccessControlException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.asm.AnnotationVisitor; -import org.springframework.asm.SpringAsmInfo; -import org.springframework.asm.Type; -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.lang.Nullable; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; - -/** - * {@link AnnotationVisitor} to recursively visit annotations. - - *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was - * removed in Spring 6 without a public replacement. - * - * @author Chris Beams - * @author Juergen Hoeller - * @author Phillip Webb - * @author Sam Brannen - * @since 3.1.1 - * @deprecated As of Spring Framework 5.2, this class and related classes in this - * package have been replaced by SimpleAnnotationMetadataReadingVisitor - * and related classes for internal use within the framework. - */ -@Deprecated -abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor { - - protected final Log logger = LogFactory.getLog(getClass()); - - protected final AnnotationAttributes attributes; - - @Nullable - protected final ClassLoader classLoader; - - - public AbstractRecursiveAnnotationVisitor(@Nullable ClassLoader classLoader, AnnotationAttributes attributes) { - super(SpringAsmInfo.ASM_VERSION); - this.classLoader = classLoader; - this.attributes = attributes; - } - - - @Override - public void visit(String attributeName, Object attributeValue) { - this.attributes.put(attributeName, attributeValue); - } - - @Override - public AnnotationVisitor visitAnnotation(String attributeName, String asmTypeDescriptor) { - String annotationType = Type.getType(asmTypeDescriptor).getClassName(); - AnnotationAttributes nestedAttributes = new AnnotationAttributes(annotationType, this.classLoader); - this.attributes.put(attributeName, nestedAttributes); - return new RecursiveAnnotationAttributesVisitor(annotationType, nestedAttributes, this.classLoader); - } - - @Override - public AnnotationVisitor visitArray(String attributeName) { - return new RecursiveAnnotationArrayVisitor(attributeName, this.attributes, this.classLoader); - } - - @Override - public void visitEnum(String attributeName, String asmTypeDescriptor, String attributeValue) { - Object newValue = getEnumValue(asmTypeDescriptor, attributeValue); - visit(attributeName, newValue); - } - - protected Object getEnumValue(String asmTypeDescriptor, String attributeValue) { - Object valueToUse = attributeValue; - try { - Class enumType = ClassUtils.forName(Type.getType(asmTypeDescriptor).getClassName(), this.classLoader); - Field enumConstant = ReflectionUtils.findField(enumType, attributeValue); - if (enumConstant != null) { - ReflectionUtils.makeAccessible(enumConstant); - valueToUse = enumConstant.get(null); - } - } - catch (ClassNotFoundException | NoClassDefFoundError ex) { - logger.debug("Failed to classload enum type while reading annotation metadata", ex); - } - catch (IllegalAccessException | AccessControlException ex) { - logger.debug("Could not access enum value while reading annotation metadata", ex); - } - return valueToUse; - } - -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java deleted file mode 100644 index 91e4bad1d05..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * 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 - * - * https://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.apache.grails.common.annotation; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Modifier; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.lang.Nullable; -import org.springframework.util.MultiValueMap; -import org.springframework.util.ObjectUtils; - -/** - * ASM visitor which looks for annotations defined on a class or method, - * including meta-annotations. - * - *

This visitor is fully recursive, taking into account any nested - * annotations or nested annotation arrays. - * - *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was - * removed in Spring 6 without a public replacement. - * - * @author Juergen Hoeller - * @author Chris Beams - * @author Phillip Webb - * @author Sam Brannen - * @since 3.0 - * @deprecated As of Spring Framework 5.2, this class and related classes in this - * package have been replaced by SimpleAnnotationMetadataReadingVisitor - * and related classes for internal use within the framework. - */ -@Deprecated -final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttributesVisitor { - - private final MultiValueMap attributesMap; - - private final Map> metaAnnotationMap; - - - public AnnotationAttributesReadingVisitor(String annotationType, - MultiValueMap attributesMap, Map> metaAnnotationMap, - @Nullable ClassLoader classLoader) { - - super(annotationType, new AnnotationAttributes(annotationType, classLoader), classLoader); - this.attributesMap = attributesMap; - this.metaAnnotationMap = metaAnnotationMap; - } - - - @Override - public void visitEnd() { - super.visitEnd(); - - Class annotationClass = this.attributes.annotationType(); - if (annotationClass != null) { - List attributeList = this.attributesMap.get(this.annotationType); - if (attributeList == null) { - this.attributesMap.add(this.annotationType, this.attributes); - } - else { - attributeList.add(0, this.attributes); - } - if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationClass.getName())) { - try { - Annotation[] metaAnnotations = annotationClass.getAnnotations(); - if (!ObjectUtils.isEmpty(metaAnnotations)) { - Set visited = new LinkedHashSet<>(); - for (Annotation metaAnnotation : metaAnnotations) { - recursivelyCollectMetaAnnotations(visited, metaAnnotation); - } - if (!visited.isEmpty()) { - Set metaAnnotationTypeNames = new LinkedHashSet<>(visited.size()); - for (Annotation ann : visited) { - metaAnnotationTypeNames.add(ann.annotationType().getName()); - } - this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames); - } - } - } - catch (Throwable ex) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to introspect meta-annotations on " + annotationClass + ": " + ex); - } - } - } - } - } - - private void recursivelyCollectMetaAnnotations(Set visited, Annotation annotation) { - Class annotationType = annotation.annotationType(); - String annotationName = annotationType.getName(); - if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) && visited.add(annotation)) { - try { - // Only do attribute scanning for public annotations; we'd run into - // IllegalAccessExceptions otherwise, and we don't want to mess with - // accessibility in a SecurityManager environment. - if (Modifier.isPublic(annotationType.getModifiers())) { - this.attributesMap.add(annotationName, - AnnotationUtils.getAnnotationAttributes(annotation, false, true)); - } - for (Annotation metaMetaAnnotation : annotationType.getAnnotations()) { - recursivelyCollectMetaAnnotations(visited, metaMetaAnnotation); - } - } - catch (Throwable ex) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to introspect meta-annotations on " + annotation + ": " + ex); - } - } - } - } - -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java deleted file mode 100644 index 664ba4afd20..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * 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 - * - * https://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.apache.grails.common.annotation; - -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.asm.AnnotationVisitor; -import org.springframework.asm.MethodVisitor; -import org.springframework.asm.Opcodes; -import org.springframework.asm.Type; -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.core.annotation.MergedAnnotations; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.MethodMetadata; -import org.springframework.lang.Nullable; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -/** - * ASM class visitor which looks for the class name and implemented types as - * well as for the annotations defined on the class, exposing them through - * the {@link org.springframework.core.type.AnnotationMetadata} interface. - * - *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was - * removed in Spring 6 without a public replacement. - * - * @author Juergen Hoeller - * @author Mark Fisher - * @author Costin Leau - * @author Phillip Webb - * @author Sam Brannen - * @since 2.5 - * @deprecated As of Spring Framework 5.2, this class has been replaced by - * SimpleAnnotationMetadataReadingVisitor for internal use within the - * framework, but there is no public replacement for - * {@code AnnotationMetadataReadingVisitor}. - */ -@Deprecated -public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata { - - @Nullable - protected final ClassLoader classLoader; - - protected final Set annotationSet = new LinkedHashSet<>(4); - - protected final Map> metaAnnotationMap = new LinkedHashMap<>(4); - - /** - * Declared as a {@link LinkedMultiValueMap} instead of a {@link MultiValueMap} - * to ensure that the hierarchical ordering of the entries is preserved. - * @see AnnotationReadingVisitorUtils#getMergedAnnotationAttributes - */ - protected final LinkedMultiValueMap attributesMap = new LinkedMultiValueMap<>(3); - - protected final Set methodMetadataSet = new LinkedHashSet<>(4); - - - public AnnotationMetadataReadingVisitor(@Nullable ClassLoader classLoader) { - this.classLoader = classLoader; - } - - - @Override - public MergedAnnotations getAnnotations() { - throw new UnsupportedOperationException(); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - // Skip bridge methods - we're only interested in original annotation-defining user methods. - // On JDK 8, we'd otherwise run into double detection of the same annotated method... - if ((access & Opcodes.ACC_BRIDGE) != 0) { - return super.visitMethod(access, name, desc, signature, exceptions); - } - return new MethodMetadataReadingVisitor(name, access, getClassName(), - Type.getReturnType(desc).getClassName(), this.classLoader, this.methodMetadataSet); - } - - @Override - @Nullable - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - if (!visible) { - return null; - } - String className = Type.getType(desc).getClassName(); - if (AnnotationUtils.isInJavaLangAnnotationPackage(className)) { - return null; - } - this.annotationSet.add(className); - return new AnnotationAttributesReadingVisitor( - className, this.attributesMap, this.metaAnnotationMap, this.classLoader); - } - - - @Override - public Set getAnnotationTypes() { - return this.annotationSet; - } - - @Override - public Set getMetaAnnotationTypes(String annotationName) { - Set metaAnnotationTypes = this.metaAnnotationMap.get(annotationName); - return (metaAnnotationTypes != null ? metaAnnotationTypes : Collections.emptySet()); - } - - @Override - public boolean hasMetaAnnotation(String metaAnnotationType) { - if (AnnotationUtils.isInJavaLangAnnotationPackage(metaAnnotationType)) { - return false; - } - Collection> allMetaTypes = this.metaAnnotationMap.values(); - for (Set metaTypes : allMetaTypes) { - if (metaTypes.contains(metaAnnotationType)) { - return true; - } - } - return false; - } - - @Override - public boolean isAnnotated(String annotationName) { - return (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) && - this.attributesMap.containsKey(annotationName)); - } - - @Override - public boolean hasAnnotation(String annotationName) { - return getAnnotationTypes().contains(annotationName); - } - - @Override - @Nullable - public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) { - AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes( - this.attributesMap, this.metaAnnotationMap, annotationName); - if (raw == null) { - return null; - } - return AnnotationReadingVisitorUtils.convertClassValues( - "class '" + getClassName() + "'", this.classLoader, raw, classValuesAsString); - } - - @Override - @Nullable - public MultiValueMap getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { - MultiValueMap allAttributes = new LinkedMultiValueMap<>(); - List attributes = this.attributesMap.get(annotationName); - if (attributes == null) { - return null; - } - String annotatedElement = "class '" + getClassName() + "'"; - for (AnnotationAttributes raw : attributes) { - for (Map.Entry entry : AnnotationReadingVisitorUtils.convertClassValues( - annotatedElement, this.classLoader, raw, classValuesAsString).entrySet()) { - allAttributes.add(entry.getKey(), entry.getValue()); - } - } - return allAttributes; - } - - @Override - public boolean hasAnnotatedMethods(String annotationName) { - for (MethodMetadata methodMetadata : this.methodMetadataSet) { - if (methodMetadata.isAnnotated(annotationName)) { - return true; - } - } - return false; - } - - @Override - public Set getAnnotatedMethods(String annotationName) { - Set annotatedMethods = new LinkedHashSet<>(4); - for (MethodMetadata methodMetadata : this.methodMetadataSet) { - if (methodMetadata.isAnnotated(annotationName)) { - annotatedMethods.add(methodMetadata); - } - } - return annotatedMethods; - } - - @Override - public Set getDeclaredMethods() { - return Set.of(); - } - -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java deleted file mode 100644 index 7b20f290afc..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * 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 - * - * https://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.apache.grails.common.annotation; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.asm.Type; -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.lang.Nullable; -import org.springframework.util.ClassUtils; -import org.springframework.util.CollectionUtils; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.ObjectUtils; - -/** - * Internal utility class used when reading annotations via ASM. - * - *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was - * removed in Spring 6 without a public replacement. - * - * @author Juergen Hoeller - * @author Mark Fisher - * @author Costin Leau - * @author Phillip Webb - * @author Sam Brannen - * @since 4.0 - * @deprecated As of Spring Framework 5.2, this class and related classes in this - * package have been replaced by SimpleAnnotationMetadataReadingVisitor - * and related classes for internal use within the framework. - */ -@Deprecated -abstract class AnnotationReadingVisitorUtils { - - public static AnnotationAttributes convertClassValues(Object annotatedElement, - @Nullable ClassLoader classLoader, AnnotationAttributes original, boolean classValuesAsString) { - - AnnotationAttributes result = new AnnotationAttributes(original); - AnnotationUtils.postProcessAnnotationAttributes(annotatedElement, result, classValuesAsString); - - for (Map.Entry entry : result.entrySet()) { - try { - Object value = entry.getValue(); - if (value instanceof AnnotationAttributes) { - value = convertClassValues( - annotatedElement, classLoader, (AnnotationAttributes) value, classValuesAsString); - } - else if (value instanceof AnnotationAttributes[]) { - AnnotationAttributes[] values = (AnnotationAttributes[]) value; - for (int i = 0; i < values.length; i++) { - values[i] = convertClassValues(annotatedElement, classLoader, values[i], classValuesAsString); - } - value = values; - } - else if (value instanceof Type) { - value = (classValuesAsString ? ((Type) value).getClassName() : - ClassUtils.forName(((Type) value).getClassName(), classLoader)); - } - else if (value instanceof Type[]) { - Type[] array = (Type[]) value; - Object[] convArray = - (classValuesAsString ? new String[array.length] : new Class[array.length]); - for (int i = 0; i < array.length; i++) { - convArray[i] = (classValuesAsString ? array[i].getClassName() : - ClassUtils.forName(array[i].getClassName(), classLoader)); - } - value = convArray; - } - else if (classValuesAsString) { - if (value instanceof Class) { - value = ((Class) value).getName(); - } - else if (value instanceof Class[]) { - Class[] clazzArray = (Class[]) value; - String[] newValue = new String[clazzArray.length]; - for (int i = 0; i < clazzArray.length; i++) { - newValue[i] = clazzArray[i].getName(); - } - value = newValue; - } - } - entry.setValue(value); - } - catch (Throwable ex) { - // Class not found - can't resolve class reference in annotation attribute. - result.put(entry.getKey(), ex); - } - } - - return result; - } - - /** - * Retrieve the merged attributes of the annotation of the given type, - * if any, from the supplied {@code attributesMap}. - *

Annotation attribute values appearing lower in the annotation - * hierarchy (i.e., closer to the declaring class) will override those - * defined higher in the annotation hierarchy. - * @param attributesMap the map of annotation attribute lists, keyed by - * annotation type name - * @param metaAnnotationMap the map of meta annotation relationships, - * keyed by annotation type name - * @param annotationName the fully qualified class name of the annotation - * type to look for - * @return the merged annotation attributes, or {@code null} if no - * matching annotation is present in the {@code attributesMap} - * @since 4.0.3 - */ - @Nullable - public static AnnotationAttributes getMergedAnnotationAttributes( - LinkedMultiValueMap attributesMap, - Map> metaAnnotationMap, String annotationName) { - - // Get the unmerged list of attributes for the target annotation. - List attributesList = attributesMap.get(annotationName); - if (CollectionUtils.isEmpty(attributesList)) { - return null; - } - - // To start with, we populate the result with a copy of all attribute values - // from the target annotation. A copy is necessary so that we do not - // inadvertently mutate the state of the metadata passed to this method. - AnnotationAttributes result = new AnnotationAttributes(attributesList.get(0)); - - Set overridableAttributeNames = new HashSet<>(result.keySet()); - overridableAttributeNames.remove(AnnotationUtils.VALUE); - - // Since the map is a LinkedMultiValueMap, we depend on the ordering of - // elements in the map and reverse the order of the keys in order to traverse - // "down" the annotation hierarchy. - List annotationTypes = new ArrayList<>(attributesMap.keySet()); - Collections.reverse(annotationTypes); - - // No need to revisit the target annotation type: - annotationTypes.remove(annotationName); - - for (String currentAnnotationType : annotationTypes) { - List currentAttributesList = attributesMap.get(currentAnnotationType); - if (!ObjectUtils.isEmpty(currentAttributesList)) { - Set metaAnns = metaAnnotationMap.get(currentAnnotationType); - if (metaAnns != null && metaAnns.contains(annotationName)) { - AnnotationAttributes currentAttributes = currentAttributesList.get(0); - for (String overridableAttributeName : overridableAttributeNames) { - Object value = currentAttributes.get(overridableAttributeName); - if (value != null) { - // Store the value, potentially overriding a value from an attribute - // of the same name found higher in the annotation hierarchy. - result.put(overridableAttributeName, value); - } - } - } - } - } - - return result; - } - -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java deleted file mode 100644 index c51cf9414ee..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * 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 - * - * https://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.apache.grails.common.annotation; - -import java.util.LinkedHashSet; -import java.util.Set; - -import org.springframework.asm.AnnotationVisitor; -import org.springframework.asm.Attribute; -import org.springframework.asm.ClassVisitor; -import org.springframework.asm.FieldVisitor; -import org.springframework.asm.MethodVisitor; -import org.springframework.asm.Opcodes; -import org.springframework.asm.SpringAsmInfo; -import org.springframework.core.type.ClassMetadata; -import org.springframework.lang.Nullable; -import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; - -/** - * ASM class visitor which looks only for the class name and implemented types, - * exposing them through the {@link org.springframework.core.type.ClassMetadata} - * interface. - * - *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was - * removed in Spring 6 without a public replacement. - * - * @author Rod Johnson - * @author Costin Leau - * @author Mark Fisher - * @author Ramnivas Laddad - * @author Chris Beams - * @since 2.5 - * @deprecated As of Spring Framework 5.2, this class and related classes in this - * package have been replaced by SimpleAnnotationMetadataReadingVisitor - * and related classes for internal use within the framework. - */ -@Deprecated -class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata { - - private String className = ""; - - private boolean isInterface; - - private boolean isAnnotation; - - private boolean isAbstract; - - private boolean isFinal; - - @Nullable - private String enclosingClassName; - - private boolean independentInnerClass; - - @Nullable - private String superClassName; - - private String[] interfaces = new String[0]; - - private Set memberClassNames = new LinkedHashSet<>(4); - - - public ClassMetadataReadingVisitor() { - super(SpringAsmInfo.ASM_VERSION); - } - - - @Override - public void visit( - int version, int access, String name, String signature, @Nullable String supername, String[] interfaces) { - - this.className = ClassUtils.convertResourcePathToClassName(name); - this.isInterface = ((access & Opcodes.ACC_INTERFACE) != 0); - this.isAnnotation = ((access & Opcodes.ACC_ANNOTATION) != 0); - this.isAbstract = ((access & Opcodes.ACC_ABSTRACT) != 0); - this.isFinal = ((access & Opcodes.ACC_FINAL) != 0); - if (supername != null && !this.isInterface) { - this.superClassName = ClassUtils.convertResourcePathToClassName(supername); - } - this.interfaces = new String[interfaces.length]; - for (int i = 0; i < interfaces.length; i++) { - this.interfaces[i] = ClassUtils.convertResourcePathToClassName(interfaces[i]); - } - } - - @Override - public void visitOuterClass(String owner, String name, String desc) { - this.enclosingClassName = ClassUtils.convertResourcePathToClassName(owner); - } - - @Override - public void visitInnerClass(String name, @Nullable String outerName, String innerName, int access) { - if (outerName != null) { - String fqName = ClassUtils.convertResourcePathToClassName(name); - String fqOuterName = ClassUtils.convertResourcePathToClassName(outerName); - if (this.className.equals(fqName)) { - this.enclosingClassName = fqOuterName; - this.independentInnerClass = ((access & Opcodes.ACC_STATIC) != 0); - } - else if (this.className.equals(fqOuterName)) { - this.memberClassNames.add(fqName); - } - } - } - - @Override - public void visitSource(String source, String debug) { - // no-op - } - - @Override - @Nullable - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - // no-op - return new EmptyAnnotationVisitor(); - } - - @Override - public void visitAttribute(Attribute attr) { - // no-op - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { - // no-op - return new EmptyFieldVisitor(); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - // no-op - return new EmptyMethodVisitor(); - } - - @Override - public void visitEnd() { - // no-op - } - - - @Override - public String getClassName() { - return this.className; - } - - @Override - public boolean isInterface() { - return this.isInterface; - } - - @Override - public boolean isAnnotation() { - return this.isAnnotation; - } - - @Override - public boolean isAbstract() { - return this.isAbstract; - } - - @Override - public boolean isFinal() { - return this.isFinal; - } - - @Override - public boolean isIndependent() { - return (this.enclosingClassName == null || this.independentInnerClass); - } - - @Override - public boolean hasEnclosingClass() { - return (this.enclosingClassName != null); - } - - @Override - @Nullable - public String getEnclosingClassName() { - return this.enclosingClassName; - } - - @Override - @Nullable - public String getSuperClassName() { - return this.superClassName; - } - - @Override - public String[] getInterfaceNames() { - return this.interfaces; - } - - @Override - public String[] getMemberClassNames() { - return StringUtils.toStringArray(this.memberClassNames); - } - - - private static class EmptyAnnotationVisitor extends AnnotationVisitor { - - public EmptyAnnotationVisitor() { - super(SpringAsmInfo.ASM_VERSION); - } - - @Override - public AnnotationVisitor visitAnnotation(String name, String desc) { - return this; - } - - @Override - public AnnotationVisitor visitArray(String name) { - return this; - } - } - - - private static class EmptyMethodVisitor extends MethodVisitor { - - public EmptyMethodVisitor() { - super(SpringAsmInfo.ASM_VERSION); - } - } - - - private static class EmptyFieldVisitor extends FieldVisitor { - - public EmptyFieldVisitor() { - super(SpringAsmInfo.ASM_VERSION); - } - } - -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java deleted file mode 100644 index 9e06949c6af..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * 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 - * - * https://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.apache.grails.common.annotation; - -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.asm.AnnotationVisitor; -import org.springframework.asm.MethodVisitor; -import org.springframework.asm.Opcodes; -import org.springframework.asm.SpringAsmInfo; -import org.springframework.asm.Type; -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.annotation.MergedAnnotations; -import org.springframework.core.type.MethodMetadata; -import org.springframework.lang.Nullable; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -/** - * ASM method visitor which looks for the annotations defined on a method, - * exposing them through the {@link org.springframework.core.type.MethodMetadata} - * interface. - * - *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was - * removed in Spring 6 without a public replacement. - * - * @author Juergen Hoeller - * @author Mark Pollack - * @author Costin Leau - * @author Chris Beams - * @author Phillip Webb - * @since 3.0 - * @deprecated As of Spring Framework 5.2, this class and related classes in this - * package have been replaced by SimpleAnnotationMetadataReadingVisitor - * and related classes for internal use within the framework. - */ -@Deprecated -public class MethodMetadataReadingVisitor extends MethodVisitor implements MethodMetadata { - - protected final String methodName; - - protected final int access; - - protected final String declaringClassName; - - protected final String returnTypeName; - - @Nullable - protected final ClassLoader classLoader; - - protected final Set methodMetadataSet; - - protected final Map> metaAnnotationMap = new LinkedHashMap<>(4); - - protected final LinkedMultiValueMap attributesMap = new LinkedMultiValueMap<>(3); - - - public MethodMetadataReadingVisitor(String methodName, int access, String declaringClassName, - String returnTypeName, @Nullable ClassLoader classLoader, Set methodMetadataSet) { - - super(SpringAsmInfo.ASM_VERSION); - this.methodName = methodName; - this.access = access; - this.declaringClassName = declaringClassName; - this.returnTypeName = returnTypeName; - this.classLoader = classLoader; - this.methodMetadataSet = methodMetadataSet; - } - - - @Override - public MergedAnnotations getAnnotations() { - throw new UnsupportedOperationException(); - } - - @Override - @Nullable - public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { - if (!visible) { - return null; - } - this.methodMetadataSet.add(this); - String className = Type.getType(desc).getClassName(); - return new AnnotationAttributesReadingVisitor( - className, this.attributesMap, this.metaAnnotationMap, this.classLoader); - } - - - @Override - public String getMethodName() { - return this.methodName; - } - - @Override - public boolean isAbstract() { - return ((this.access & Opcodes.ACC_ABSTRACT) != 0); - } - - @Override - public boolean isStatic() { - return ((this.access & Opcodes.ACC_STATIC) != 0); - } - - @Override - public boolean isFinal() { - return ((this.access & Opcodes.ACC_FINAL) != 0); - } - - @Override - public boolean isOverridable() { - return (!isStatic() && !isFinal() && ((this.access & Opcodes.ACC_PRIVATE) == 0)); - } - - @Override - public boolean isAnnotated(String annotationName) { - return this.attributesMap.containsKey(annotationName); - } - - @Override - @Nullable - public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) { - AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes( - this.attributesMap, this.metaAnnotationMap, annotationName); - if (raw == null) { - return null; - } - return AnnotationReadingVisitorUtils.convertClassValues( - "method '" + getMethodName() + "'", this.classLoader, raw, classValuesAsString); - } - - @Override - @Nullable - public MultiValueMap getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { - if (!this.attributesMap.containsKey(annotationName)) { - return null; - } - MultiValueMap allAttributes = new LinkedMultiValueMap<>(); - List attributesList = this.attributesMap.get(annotationName); - if (attributesList != null) { - String annotatedElement = "method '" + getMethodName() + '\''; - for (AnnotationAttributes annotationAttributes : attributesList) { - AnnotationAttributes convertedAttributes = AnnotationReadingVisitorUtils.convertClassValues( - annotatedElement, this.classLoader, annotationAttributes, classValuesAsString); - convertedAttributes.forEach(allAttributes::add); - } - } - return allAttributes; - } - - @Override - public String getDeclaringClassName() { - return this.declaringClassName; - } - - @Override - public String getReturnTypeName() { - return this.returnTypeName; - } - -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java deleted file mode 100644 index d7ee022739c..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * 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 - * - * https://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.apache.grails.common.annotation; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.asm.AnnotationVisitor; -import org.springframework.asm.Type; -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.lang.Nullable; -import org.springframework.util.ObjectUtils; - -/** - * {@link AnnotationVisitor} to recursively visit annotation arrays. - * - *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was - * removed in Spring 6 without a public replacement. - * - * @author Chris Beams - * @author Juergen Hoeller - * @since 3.1.1 - * @deprecated As of Spring Framework 5.2, this class and related classes in this - * package have been replaced by SimpleAnnotationMetadataReadingVisitor - * and related classes for internal use within the framework. - */ -@Deprecated -class RecursiveAnnotationArrayVisitor extends AbstractRecursiveAnnotationVisitor { - - private final String attributeName; - - private final List allNestedAttributes = new ArrayList<>(); - - - public RecursiveAnnotationArrayVisitor( - String attributeName, AnnotationAttributes attributes, @Nullable ClassLoader classLoader) { - - super(classLoader, attributes); - this.attributeName = attributeName; - } - - - @Override - public void visit(String attributeName, Object attributeValue) { - Object newValue = attributeValue; - Object existingValue = this.attributes.get(this.attributeName); - if (existingValue != null) { - newValue = ObjectUtils.addObjectToArray((Object[]) existingValue, newValue); - } - else { - Class arrayClass = newValue.getClass(); - if (Enum.class.isAssignableFrom(arrayClass)) { - while (arrayClass.getSuperclass() != null && !arrayClass.isEnum()) { - arrayClass = arrayClass.getSuperclass(); - } - } - Object[] newArray = (Object[]) Array.newInstance(arrayClass, 1); - newArray[0] = newValue; - newValue = newArray; - } - this.attributes.put(this.attributeName, newValue); - } - - @Override - public AnnotationVisitor visitAnnotation(String attributeName, String asmTypeDescriptor) { - String annotationType = Type.getType(asmTypeDescriptor).getClassName(); - AnnotationAttributes nestedAttributes = new AnnotationAttributes(annotationType, this.classLoader); - this.allNestedAttributes.add(nestedAttributes); - return new RecursiveAnnotationAttributesVisitor(annotationType, nestedAttributes, this.classLoader); - } - - @Override - public void visitEnd() { - if (!this.allNestedAttributes.isEmpty()) { - this.attributes.put(this.attributeName, this.allNestedAttributes.toArray(new AnnotationAttributes[0])); - } - else if (!this.attributes.containsKey(this.attributeName)) { - Class annotationType = this.attributes.annotationType(); - if (annotationType != null) { - try { - Class attributeType = annotationType.getMethod(this.attributeName).getReturnType(); - if (attributeType.isArray()) { - Class elementType = attributeType.getComponentType(); - if (elementType.isAnnotation()) { - elementType = AnnotationAttributes.class; - } - this.attributes.put(this.attributeName, Array.newInstance(elementType, 0)); - } - } - catch (NoSuchMethodException ex) { - // Corresponding attribute method not found: cannot expose empty array. - } - } - } - } - -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java deleted file mode 100644 index dc8b935d1a6..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * 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 - * - * https://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.apache.grails.common.annotation; - -import org.springframework.asm.AnnotationVisitor; -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.lang.Nullable; - -/** - * {@link AnnotationVisitor} to recursively visit annotation attributes. - * - *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was - * removed in Spring 6 without a public replacement. - * - * @author Chris Beams - * @author Juergen Hoeller - * @since 3.1.1 - * @deprecated As of Spring Framework 5.2, this class and related classes in this - * package have been replaced by SimpleAnnotationMetadataReadingVisitor - * and related classes for internal use within the framework. - */ -@Deprecated -class RecursiveAnnotationAttributesVisitor extends AbstractRecursiveAnnotationVisitor { - - protected final String annotationType; - - - public RecursiveAnnotationAttributesVisitor( - String annotationType, AnnotationAttributes attributes, @Nullable ClassLoader classLoader) { - - super(classLoader, attributes); - this.annotationType = annotationType; - } - - - @Override - public void visitEnd() { - AnnotationUtils.registerDefaultValues(this.attributes); - } - -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java deleted file mode 100644 index 98a5342bdec..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * https://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.apache.grails.common.compiler.asm; - -import org.apache.grails.common.annotation.AnnotationMetadataReadingVisitor; -import org.springframework.asm.AnnotationVisitor; -import org.springframework.asm.SpringAsmInfo; -import org.springframework.asm.Type; -import org.springframework.core.io.Resource; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.ClassMetadata; -import org.springframework.core.type.classreading.MetadataReader; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * A more limited version of Spring's annotation reader that only reads annotations on classes - * - * @author Graeme Rocher - * @since 3.1.13 - */ -public class AnnotationMetadataReader implements MetadataReader { - private final Resource resource; - - private final ClassMetadata classMetadata; - - private final AnnotationMetadata annotationMetadata; - - /** - * Reads only the annotation names from a class resource - * @param resource The resource - * @param classLoader The classloader - * @throws IOException - */ - public AnnotationMetadataReader(Resource resource, ClassLoader classLoader) throws IOException { - this(resource, classLoader, false); - } - /** - * Constructs a new annotation metadata reader - * - * @param resource The resource - * @param classLoader The classloader - * @param readAttributeValues Whether to read the attributes in addition or just the annotation class names - * @throws IOException - */ - public AnnotationMetadataReader(Resource resource, ClassLoader classLoader, boolean readAttributeValues) throws IOException { - InputStream is = new BufferedInputStream(resource.getInputStream()); - ClassReader classReader; - try { - classReader = new ClassReader(is); - } - catch (IllegalArgumentException ex) { - throw new IOException("ASM ClassReader failed to parse class file - " + - "probably due to a new Java class file version that isn't supported yet: " + resource, ex); - } - finally { - is.close(); - } - - - AnnotationMetadataReadingVisitor visitor; - - if(readAttributeValues) { - visitor = new AnnotationMetadataReadingVisitor(classLoader); - } - else { - visitor = new AnnotationMetadataReadingVisitor(classLoader) { - @Override - public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { - String className = Type.getType(desc).getClassName(); - this.annotationSet.add(className); - return new EmptyAnnotationVisitor(); - } - }; - } - classReader.accept(visitor, ClassReader.SKIP_DEBUG); - - this.annotationMetadata = visitor; - // (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor) - this.classMetadata = visitor; - this.resource = resource; - } - - - @Override - public Resource getResource() { - return this.resource; - } - - @Override - public ClassMetadata getClassMetadata() { - return this.classMetadata; - } - - @Override - public AnnotationMetadata getAnnotationMetadata() { - return this.annotationMetadata; - } - - private static class EmptyAnnotationVisitor extends AnnotationVisitor { - - EmptyAnnotationVisitor() { - super(loadAsmVersion()); - } - - private static int loadAsmVersion() { - try { - // Load the ASM version using reflection to prevent the compiler from replacing the reference - // with the value. This it soupport different verisons of spring. - return (int) SpringAsmInfo.class.getField("ASM_VERSION").get(null); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public AnnotationVisitor visitAnnotation(String name, String desc) { - return this; - } - - @Override - public AnnotationVisitor visitArray(String name) { - return this; - } - } -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java deleted file mode 100644 index 356d618d192..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java +++ /dev/null @@ -1,258 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.apache.grails.common.compiler.asm; - -import org.springframework.asm.ClassWriter; -import org.springframework.asm.Label; - -/** - * A non standard class, field, method or code attribute. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -class Attribute { - - /** - * The type of this attribute. - */ - public final String type; - - /** - * The raw value of this attribute, used only for unknown attributes. - */ - byte[] value; - - /** - * The next attribute in this attribute list. May be null. - */ - Attribute next; - - /** - * Constructs a new empty attribute. - * - * @param type - * the type of the attribute. - */ - protected Attribute(final String type) { - this.type = type; - } - - /** - * Returns true if this type of attribute is unknown. The default - * implementation of this method always returns true. - * - * @return true if this type of attribute is unknown. - */ - public boolean isUnknown() { - return true; - } - - /** - * Returns true if this type of attribute is a code attribute. - * - * @return true if this type of attribute is a code attribute. - */ - public boolean isCodeAttribute() { - return false; - } - - /** - * Returns the labels corresponding to this attribute. - * - * @return the labels corresponding to this attribute, or null if - * this attribute is not a code attribute that contains labels. - */ - protected Label[] getLabels() { - return null; - } - - /** - * Reads a {@link #type type} attribute. This method must return a - * new {@link Attribute} object, of type {@link #type type}, - * corresponding to the len bytes starting at the given offset, in - * the given class reader. - * - * @param cr - * the class that contains the attribute to be read. - * @param off - * index of the first byte of the attribute's content in - * {@link ClassReader#b cr.b}. The 6 attribute header bytes, - * containing the type and the length of the attribute, are not - * taken into account here. - * @param len - * the length of the attribute's content. - * @param buf - * buffer to be used to call {@link ClassReader#readUTF8 - * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass} - * or {@link ClassReader#readConst readConst}. - * @param codeOff - * index of the first byte of code's attribute content in - * {@link ClassReader#b cr.b}, or -1 if the attribute to be read - * is not a code attribute. The 6 attribute header bytes, - * containing the type and the length of the attribute, are not - * taken into account here. - * @param labels - * the labels of the method's code, or null if the - * attribute to be read is not a code attribute. - * @return a new {@link Attribute} object corresponding to the given - * bytes. - */ - protected Attribute read(final ClassReader cr, final int off, - final int len, final char[] buf, final int codeOff, - final Label[] labels) { - Attribute attr = new Attribute(type); - attr.value = new byte[len]; - System.arraycopy(cr.b, off, attr.value, 0, len); - return attr; - } - - /** - * Returns the byte array form of this attribute. - * - * @param cw - * the class to which this attribute must be added. This - * parameter can be used to add to the constant pool of this - * class the items that corresponds to this attribute. - * @param code - * the bytecode of the method corresponding to this code - * attribute, or null if this attribute is not a code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to this - * code attribute, or null if this attribute is not a - * code attribute. - * @param maxStack - * the maximum stack size of the method corresponding to this - * code attribute, or -1 if this attribute is not a code - * attribute. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to this code attribute, or -1 if this attribute - * is not a code attribute. - * @return the byte array form of this attribute. - */ - protected ByteVector write(final ClassWriter cw, final byte[] code, - final int len, final int maxStack, final int maxLocals) { - ByteVector v = new ByteVector(); - v.data = value; - v.length = value.length; - return v; - } - - /** - * Returns the length of the attribute list that begins with this attribute. - * - * @return the length of the attribute list that begins with this attribute. - */ - final int getCount() { - int count = 0; - Attribute attr = this; - while (attr != null) { - count += 1; - attr = attr.next; - } - return count; - } - - /** - * Returns the size of all the attributes in this attribute list. - * - * @param cw - * the class writer to be used to convert the attributes into - * byte arrays, with the {@link #write write} method. - * @param code - * the bytecode of the method corresponding to these code - * attributes, or null if these attributes are not code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to - * these code attributes, or null if these attributes - * are not code attributes. - * @param maxStack - * the maximum stack size of the method corresponding to these - * code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these - * attributes are not code attributes. - * @return the size of all the attributes in this attribute list. This size - * includes the size of the attribute headers. - */ - final int getSize(final ClassWriter cw, final byte[] code, final int len, - final int maxStack, final int maxLocals) { - Attribute attr = this; - int size = 0; - while (attr != null) { - cw.newUTF8(attr.type); - size += attr.write(cw, code, len, maxStack, maxLocals).length + 6; - attr = attr.next; - } - return size; - } - - /** - * Writes all the attributes of this attribute list in the given byte - * vector. - * - * @param cw - * the class writer to be used to convert the attributes into - * byte arrays, with the {@link #write write} method. - * @param code - * the bytecode of the method corresponding to these code - * attributes, or null if these attributes are not code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to - * these code attributes, or null if these attributes - * are not code attributes. - * @param maxStack - * the maximum stack size of the method corresponding to these - * code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these - * attributes are not code attributes. - * @param out - * where the attributes must be written. - */ - final void put(final ClassWriter cw, final byte[] code, final int len, - final int maxStack, final int maxLocals, final ByteVector out) { - Attribute attr = this; - while (attr != null) { - ByteVector b = attr.write(cw, code, len, maxStack, maxLocals); - out.putShort(cw.newUTF8(attr.type)).putInt(b.length); - out.putByteArray(b.data, 0, b.length); - attr = attr.next; - } - } -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java deleted file mode 100644 index d3f08fdb14a..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java +++ /dev/null @@ -1,339 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.apache.grails.common.compiler.asm; - -/** - * A dynamically extensible vector of bytes. This class is roughly equivalent to - * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient. - * - * @author Eric Bruneton - */ -class ByteVector { - - /** - * The content of this vector. - */ - byte[] data; - - /** - * Actual number of bytes in this vector. - */ - int length; - - /** - * Constructs a new {@link ByteVector ByteVector} with a default initial - * size. - */ - public ByteVector() { - data = new byte[64]; - } - - /** - * Constructs a new {@link ByteVector ByteVector} with the given initial - * size. - * - * @param initialSize - * the initial size of the byte vector to be constructed. - */ - public ByteVector(final int initialSize) { - data = new byte[initialSize]; - } - - /** - * Puts a byte into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param b - * a byte. - * @return this byte vector. - */ - public ByteVector putByte(final int b) { - int length = this.length; - if (length + 1 > data.length) { - enlarge(1); - } - data[length++] = (byte) b; - this.length = length; - return this; - } - - /** - * Puts two bytes into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param b1 - * a byte. - * @param b2 - * another byte. - * @return this byte vector. - */ - ByteVector put11(final int b1, final int b2) { - int length = this.length; - if (length + 2 > data.length) { - enlarge(2); - } - byte[] data = this.data; - data[length++] = (byte) b1; - data[length++] = (byte) b2; - this.length = length; - return this; - } - - /** - * Puts a short into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param s - * a short. - * @return this byte vector. - */ - public ByteVector putShort(final int s) { - int length = this.length; - if (length + 2 > data.length) { - enlarge(2); - } - byte[] data = this.data; - data[length++] = (byte) (s >>> 8); - data[length++] = (byte) s; - this.length = length; - return this; - } - - /** - * Puts a byte and a short into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param b - * a byte. - * @param s - * a short. - * @return this byte vector. - */ - ByteVector put12(final int b, final int s) { - int length = this.length; - if (length + 3 > data.length) { - enlarge(3); - } - byte[] data = this.data; - data[length++] = (byte) b; - data[length++] = (byte) (s >>> 8); - data[length++] = (byte) s; - this.length = length; - return this; - } - - /** - * Puts an int into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param i - * an int. - * @return this byte vector. - */ - public ByteVector putInt(final int i) { - int length = this.length; - if (length + 4 > data.length) { - enlarge(4); - } - byte[] data = this.data; - data[length++] = (byte) (i >>> 24); - data[length++] = (byte) (i >>> 16); - data[length++] = (byte) (i >>> 8); - data[length++] = (byte) i; - this.length = length; - return this; - } - - /** - * Puts a long into this byte vector. The byte vector is automatically - * enlarged if necessary. - * - * @param l - * a long. - * @return this byte vector. - */ - public ByteVector putLong(final long l) { - int length = this.length; - if (length + 8 > data.length) { - enlarge(8); - } - byte[] data = this.data; - int i = (int) (l >>> 32); - data[length++] = (byte) (i >>> 24); - data[length++] = (byte) (i >>> 16); - data[length++] = (byte) (i >>> 8); - data[length++] = (byte) i; - i = (int) l; - data[length++] = (byte) (i >>> 24); - data[length++] = (byte) (i >>> 16); - data[length++] = (byte) (i >>> 8); - data[length++] = (byte) i; - this.length = length; - return this; - } - - /** - * Puts an UTF8 string into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param s - * a String whose UTF8 encoded length must be less than 65536. - * @return this byte vector. - */ - public ByteVector putUTF8(final String s) { - int charLength = s.length(); - if (charLength > 65535) { - throw new IllegalArgumentException(); - } - int len = length; - if (len + 2 + charLength > data.length) { - enlarge(2 + charLength); - } - byte[] data = this.data; - // optimistic algorithm: instead of computing the byte length and then - // serializing the string (which requires two loops), we assume the byte - // length is equal to char length (which is the most frequent case), and - // we start serializing the string right away. During the serialization, - // if we find that this assumption is wrong, we continue with the - // general method. - data[len++] = (byte) (charLength >>> 8); - data[len++] = (byte) charLength; - for (int i = 0; i < charLength; ++i) { - char c = s.charAt(i); - if (c >= '\001' && c <= '\177') { - data[len++] = (byte) c; - } else { - length = len; - return encodeUTF8(s, i, 65535); - } - } - length = len; - return this; - } - - /** - * Puts an UTF8 string into this byte vector. The byte vector is - * automatically enlarged if necessary. The string length is encoded in two - * bytes before the encoded characters, if there is space for that (i.e. if - * this.length - i - 2 >= 0). - * - * @param s - * the String to encode. - * @param i - * the index of the first character to encode. The previous - * characters are supposed to have already been encoded, using - * only one byte per character. - * @param maxByteLength - * the maximum byte length of the encoded string, including the - * already encoded characters. - * @return this byte vector. - */ - ByteVector encodeUTF8(final String s, int i, int maxByteLength) { - int charLength = s.length(); - int byteLength = i; - char c; - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - byteLength++; - } else if (c > '\u07FF') { - byteLength += 3; - } else { - byteLength += 2; - } - } - if (byteLength > maxByteLength) { - throw new IllegalArgumentException(); - } - int start = length - i - 2; - if (start >= 0) { - data[start] = (byte) (byteLength >>> 8); - data[start + 1] = (byte) byteLength; - } - if (length + byteLength - i > data.length) { - enlarge(byteLength - i); - } - int len = length; - for (int j = i; j < charLength; ++j) { - c = s.charAt(j); - if (c >= '\001' && c <= '\177') { - data[len++] = (byte) c; - } else if (c > '\u07FF') { - data[len++] = (byte) (0xE0 | c >> 12 & 0xF); - data[len++] = (byte) (0x80 | c >> 6 & 0x3F); - data[len++] = (byte) (0x80 | c & 0x3F); - } else { - data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); - data[len++] = (byte) (0x80 | c & 0x3F); - } - } - length = len; - return this; - } - - /** - * Puts an array of bytes into this byte vector. The byte vector is - * automatically enlarged if necessary. - * - * @param b - * an array of bytes. May be null to put len - * null bytes into this byte vector. - * @param off - * index of the fist byte of b that must be copied. - * @param len - * number of bytes of b that must be copied. - * @return this byte vector. - */ - public ByteVector putByteArray(final byte[] b, final int off, final int len) { - if (length + len > data.length) { - enlarge(len); - } - if (b != null) { - System.arraycopy(b, off, data, length, len); - } - length += len; - return this; - } - - /** - * Enlarge this byte vector so that it can receive n more bytes. - * - * @param size - * number of additional bytes that this byte vector should be - * able to receive. - */ - private void enlarge(final int size) { - int length1 = 2 * data.length; - int length2 = length + size; - byte[] newData = new byte[length1 > length2 ? length1 : length2]; - System.arraycopy(data, 0, newData, 0, length); - data = newData; - } -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java deleted file mode 100644 index e7afd738836..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java +++ /dev/null @@ -1,1056 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.apache.grails.common.compiler.asm; - -import org.springframework.asm.*; -import java.io.IOException; -import java.io.InputStream; - -/** - * A Java class parser to make a {@link org.springframework.asm.ClassVisitor} visit an existing class. - * This class parses a byte array conforming to the Java class file format and - * calls the appropriate visit methods of a given class visitor for each field, - * method and bytecode instruction encountered. - * - * @author Eric Bruneton - * @author Eugene Kuleshov - */ -class ClassReader { - /** - * Pseudo access flag to distinguish between the synthetic attribute and the - * synthetic access flag. - */ - static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000; - - - /** - * The type of CONSTANT_Class constant pool items. - */ - static final int CLASS = 7; - - /** - * The type of CONSTANT_Fieldref constant pool items. - */ - static final int FIELD = 9; - - /** - * The type of CONSTANT_Methodref constant pool items. - */ - static final int METH = 10; - - /** - * The type of CONSTANT_InterfaceMethodref constant pool items. - */ - static final int IMETH = 11; - - /** - * The type of CONSTANT_String constant pool items. - */ - static final int STR = 8; - - /** - * The type of CONSTANT_Integer constant pool items. - */ - static final int INT = 3; - - /** - * The type of CONSTANT_Float constant pool items. - */ - static final int FLOAT = 4; - - /** - * The type of CONSTANT_Long constant pool items. - */ - static final int LONG = 5; - - /** - * The type of CONSTANT_Double constant pool items. - */ - static final int DOUBLE = 6; - - /** - * The type of CONSTANT_NameAndType constant pool items. - */ - static final int NAME_TYPE = 12; - - /** - * The type of CONSTANT_Utf8 constant pool items. - */ - static final int UTF8 = 1; - - /** - * The type of CONSTANT_MethodType constant pool items. - */ - static final int MTYPE = 16; - - /** - * The type of CONSTANT_MethodHandle constant pool items. - */ - static final int HANDLE = 15; - - /** - * The type of CONSTANT_InvokeDynamic constant pool items. - */ - static final int INDY = 18; - - /** - * True to enable signatures support. - */ - static final boolean SIGNATURES = true; - - /** - * True to enable annotations support. - */ - static final boolean ANNOTATIONS = true; - - - /** - * Flag to skip the debug information in the class. If this flag is set the - * debug information of the class is not visited, i.e. the - * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and - * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be - * called. - */ - public static final int SKIP_DEBUG = 2; - - /** - * The class to be parsed. The content of this array must not be - * modified. This field is intended for {@link Attribute} sub classes, and - * is normally not needed by class generators or adapters. - */ - public final byte[] b; - - /** - * The start index of each constant pool item in {@link #b b}, plus one. The - * one byte offset skips the constant pool item tag that indicates its type. - */ - private final int[] items; - - /** - * The String objects corresponding to the CONSTANT_Utf8 items. This cache - * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item, - * which GREATLY improves performances (by a factor 2 to 3). This caching - * strategy could be extended to all constant pool items, but its benefit - * would not be so great for these items (because they are much less - * expensive to parse than CONSTANT_Utf8 items). - */ - private final String[] strings; - - /** - * Maximum length of the strings contained in the constant pool of the - * class. - */ - private final int maxStringLength; - - /** - * Start index of the class header information (access, name...) in - * {@link #b b}. - */ - public final int header; - - // ------------------------------------------------------------------------ - // Constructors - // ------------------------------------------------------------------------ - - /** - * Constructs a new {@link ClassReader} object. - * - * @param b - * the bytecode of the class to be read. - */ - private ClassReader(final byte[] b) { - this(b, 0, b.length); - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param b - * the bytecode of the class to be read. - * @param off - * the start offset of the class data. - * @param len - * the length of the class data. - */ - public ClassReader(final byte[] b, final int off, final int len) { - this.b = b; - // checks the class version - /* SPRING PATCH: REMOVED FOR FORWARD COMPATIBILITY WITH JDK 9 - if (readShort(off + 6) > Opcodes.V1_8) { - throw new IllegalArgumentException(); - } - */ - // parses the constant pool - items = new int[readUnsignedShort(off + 8)]; - int n = items.length; - strings = new String[n]; - int max = 0; - int index = off + 10; - for (int i = 1; i < n; ++i) { - items[i] = index + 1; - int size; - switch (b[index]) { - case FIELD: - case METH: - case IMETH: - case INT: - case FLOAT: - case NAME_TYPE: - case INDY: - size = 5; - break; - case LONG: - case DOUBLE: - size = 9; - ++i; - break; - case UTF8: - size = 3 + readUnsignedShort(index + 1); - if (size > max) { - max = size; - } - break; - case HANDLE: - size = 4; - break; - // case ClassWriter.CLASS: - // case ClassWriter.STR: - // case ClassWriter.MTYPE - default: - size = 3; - break; - } - index += size; - } - maxStringLength = max; - // the class header information starts just after the constant pool - header = index; - } - - /** - * Returns the class's access flags (see {@link Opcodes}). This value may - * not reflect Deprecated and Synthetic flags when bytecode is before 1.5 - * and those flags are represented by attributes. - * - * @return the class access flags - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public int getAccess() { - return readUnsignedShort(header); - } - - /** - * Returns the internal name of the class (see - * {@link Type#getInternalName() getInternalName}). - * - * @return the internal class name - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public String getClassName() { - return readClass(header + 2, new char[maxStringLength]); - } - - /** - * Returns the internal of name of the super class (see - * {@link Type#getInternalName() getInternalName}). For interfaces, the - * super class is {@link Object}. - * - * @return the internal name of super class, or null for - * {@link Object} class. - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public String getSuperName() { - return readClass(header + 4, new char[maxStringLength]); - } - - /** - * Returns the internal names of the class's interfaces (see - * {@link Type#getInternalName() getInternalName}). - * - * @return the array of internal names for all implemented interfaces or - * null. - * - * @see ClassVisitor#visit(int, int, String, String, String, String[]) - */ - public String[] getInterfaces() { - int index = header + 6; - int n = readUnsignedShort(index); - String[] interfaces = new String[n]; - if (n > 0) { - char[] buf = new char[maxStringLength]; - for (int i = 0; i < n; ++i) { - index += 2; - interfaces[i] = readClass(index, buf); - } - } - return interfaces; - } - - - - - - /** - * Constructs a new {@link ClassReader} object. - * - * @param is - * an input stream from which to read the class. - * @throws IOException - * if a problem occurs during reading. - */ - public ClassReader(final InputStream is) throws IOException { - this(readClass(is, false)); - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param name - * the binary qualified name of the class to be read. - * @throws IOException - * if an exception occurs during reading. - */ - public ClassReader(final String name) throws IOException { - this(readClass( - ClassLoader.getSystemResourceAsStream(name.replace('.', '/') - + ".class"), true)); - } - - /** - * Reads the bytecode of a class. - * - * @param is - * an input stream from which to read the class. - * @param close - * true to close the input stream after reading. - * @return the bytecode read from the given input stream. - * @throws IOException - * if a problem occurs during reading. - */ - private static byte[] readClass(final InputStream is, boolean close) - throws IOException { - if (is == null) { - throw new IOException("Class not found"); - } - try { - byte[] b = new byte[is.available()]; - int len = 0; - while (true) { - int n = is.read(b, len, b.length - len); - if (n == -1) { - if (len < b.length) { - byte[] c = new byte[len]; - System.arraycopy(b, 0, c, 0, len); - b = c; - } - return b; - } - len += n; - if (len == b.length) { - int last = is.read(); - if (last < 0) { - return b; - } - byte[] c = new byte[b.length + 1000]; - System.arraycopy(b, 0, c, 0, len); - c[len++] = (byte) last; - b = c; - } - } - } finally { - if (close) { - is.close(); - } - } - } - - // ------------------------------------------------------------------------ - // Public methods - // ------------------------------------------------------------------------ - - /** - * Makes the given visitor visit the Java class of this {@link ClassReader} - * . This class is the one specified in the constructor (see - * {@link #ClassReader(byte[]) ClassReader}). - * - * @param classVisitor - * the visitor that must visit this class. - */ - public void accept(final ClassVisitor classVisitor, final int flags) { - accept(classVisitor, new Attribute[0], flags); - } - - /** - * Makes the given visitor visit the Java class of this {@link ClassReader}. - * This class is the one specified in the constructor (see - * {@link #ClassReader(byte[]) ClassReader}). - * - * @param classVisitor - * the visitor that must visit this class. - * @param attrs - * prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to - * the type of one the prototypes will not be parsed: its byte - * array value will be passed unchanged to the ClassWriter. - * This may corrupt it if this value contains references to - * the constant pool, or has syntactic or semantic links with a - * class element that has been transformed by a class adapter - * between the reader and the writer. - */ - public void accept(final ClassVisitor classVisitor, - final Attribute[] attrs, final int flags) { - int u = header; // current offset in the class file - char[] c = new char[maxStringLength]; // buffer used to read strings - - Context context = new Context(); - context.attrs = attrs; - context.flags = flags; - context.buffer = c; - - // reads the class declaration - int access = readUnsignedShort(u); - String name = readClass(u + 2, c); - String superClass = readClass(u + 4, c); - String[] interfaces = new String[readUnsignedShort(u + 6)]; - u += 8; - for (int i = 0; i < interfaces.length; ++i) { - interfaces[i] = readClass(u, c); - u += 2; - } - - // reads the class attributes - String signature = null; - String sourceFile = null; - String sourceDebug = null; - String enclosingOwner = null; - String enclosingName = null; - String enclosingDesc = null; - int anns = 0; - int ianns = 0; - int tanns = 0; - int itanns = 0; - int innerClasses = 0; - Attribute attributes = null; - - u = getAttributes(); - for (int i = readUnsignedShort(u); i > 0; --i) { - String attrName = readUTF8(u + 2, c); - // tests are sorted in decreasing frequency order - // (based on frequencies observed on typical classes) - if ("SourceFile".equals(attrName)) { - sourceFile = readUTF8(u + 8, c); - } else if ("InnerClasses".equals(attrName)) { - innerClasses = u + 8; - } else if ("EnclosingMethod".equals(attrName)) { - enclosingOwner = readClass(u + 8, c); - int item = readUnsignedShort(u + 10); - if (item != 0) { - enclosingName = readUTF8(items[item], c); - enclosingDesc = readUTF8(items[item] + 2, c); - } - } else if (SIGNATURES && "Signature".equals(attrName)) { - signature = readUTF8(u + 8, c); - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { - anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { - tanns = u + 8; - } else if ("Deprecated".equals(attrName)) { - access |= Opcodes.ACC_DEPRECATED; - } else if ("Synthetic".equals(attrName)) { - access |= Opcodes.ACC_SYNTHETIC - | ACC_SYNTHETIC_ATTRIBUTE; - } else if ("SourceDebugExtension".equals(attrName)) { - int len = readInt(u + 4); - sourceDebug = readUTF(u + 8, len, new char[len]); - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { - ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { - itanns = u + 8; - } else if ("BootstrapMethods".equals(attrName)) { - int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; - for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { - bootstrapMethods[j] = v; - v += 2 + readUnsignedShort(v + 2) << 1; - } - context.bootstrapMethods = bootstrapMethods; - } else { - Attribute attr = readAttribute(attrs, attrName, u + 8, - readInt(u + 4), c, -1, null); - if (attr != null) { - attr.next = attributes; - attributes = attr; - } - } - u += 6 + readInt(u + 4); - } - - // visits the class declaration - classVisitor.visit(readInt(items[1] - 7), access, name, signature, - superClass, interfaces); - - // visits the source and debug info - if ((flags & SKIP_DEBUG) == 0 - && (sourceFile != null || sourceDebug != null)) { - classVisitor.visitSource(sourceFile, sourceDebug); - } - - // visits the outer class - if (enclosingOwner != null) { - classVisitor.visitOuterClass(enclosingOwner, enclosingName, - enclosingDesc); - } - - // visits the class annotations and type annotations - if (ANNOTATIONS && anns != 0) { - for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitAnnotation(readUTF8(v, c), true)); - } - } - if (ANNOTATIONS && ianns != 0) { - for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitAnnotation(readUTF8(v, c), false)); - } - } - - // visits the end of the class - classVisitor.visitEnd(); - } - - /** - * Reads the values of an annotation and makes the given visitor visit them. - * - * @param v - * the start offset in {@link #b b} of the values to be read - * (including the unsigned short that gives the number of - * values). - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param named - * if the annotation values are named or not. - * @param av - * the visitor that must visit the values. - * @return the end offset of the annotation values. - */ - private int readAnnotationValues(int v, final char[] buf, - final boolean named, final AnnotationVisitor av) { - int i = readUnsignedShort(v); - v += 2; - if (named) { - for (; i > 0; --i) { - v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av); - } - } else { - for (; i > 0; --i) { - v = readAnnotationValue(v, buf, null, av); - } - } - if (av != null) { - av.visitEnd(); - } - return v; - } - - /** - * Reads a value of an annotation and makes the given visitor visit it. - * - * @param v - * the start offset in {@link #b b} of the value to be read - * (not including the value name constant pool index). - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param name - * the name of the value to be read. - * @param av - * the visitor that must visit the value. - * @return the end offset of the annotation value. - */ - private int readAnnotationValue(int v, final char[] buf, final String name, - final AnnotationVisitor av) { - int i; - if (av == null) { - switch (b[v] & 0xFF) { - case 'e': // enum_const_value - return v + 5; - case '@': // annotation_value - return readAnnotationValues(v + 3, buf, true, null); - case '[': // array_value - return readAnnotationValues(v + 1, buf, false, null); - default: - return v + 3; - } - } - switch (b[v++] & 0xFF) { - case 'I': // pointer to CONSTANT_Integer - case 'J': // pointer to CONSTANT_Long - case 'F': // pointer to CONSTANT_Float - case 'D': // pointer to CONSTANT_Double - av.visit(name, readConst(readUnsignedShort(v), buf)); - v += 2; - break; - case 'B': // pointer to CONSTANT_Byte - av.visit(name, (byte) readInt(items[readUnsignedShort(v)])); - v += 2; - break; - case 'Z': // pointer to CONSTANT_Boolean - av.visit(name, readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE : Boolean.TRUE); - v += 2; - break; - case 'S': // pointer to CONSTANT_Short - av.visit(name, (short) readInt(items[readUnsignedShort(v)])); - v += 2; - break; - case 'C': // pointer to CONSTANT_Char - av.visit(name, (char) readInt(items[readUnsignedShort(v)])); - v += 2; - break; - case 's': // pointer to CONSTANT_Utf8 - av.visit(name, readUTF8(v, buf)); - v += 2; - break; - case 'e': // enum_const_value - av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); - v += 4; - break; - case 'c': // class_info - av.visit(name, Type.getType(readUTF8(v, buf))); - v += 2; - break; - case '@': // annotation_value - v = readAnnotationValues(v + 2, buf, true, - av.visitAnnotation(name, readUTF8(v, buf))); - break; - case '[': // array_value - int size = readUnsignedShort(v); - v += 2; - if (size == 0) { - return readAnnotationValues(v - 2, buf, false, - av.visitArray(name)); - } - switch (this.b[v++] & 0xFF) { - case 'B': - byte[] bv = new byte[size]; - for (i = 0; i < size; i++) { - bv[i] = (byte) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, bv); - --v; - break; - case 'Z': - boolean[] zv = new boolean[size]; - for (i = 0; i < size; i++) { - zv[i] = readInt(items[readUnsignedShort(v)]) != 0; - v += 3; - } - av.visit(name, zv); - --v; - break; - case 'S': - short[] sv = new short[size]; - for (i = 0; i < size; i++) { - sv[i] = (short) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, sv); - --v; - break; - case 'C': - char[] cv = new char[size]; - for (i = 0; i < size; i++) { - cv[i] = (char) readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, cv); - --v; - break; - case 'I': - int[] iv = new int[size]; - for (i = 0; i < size; i++) { - iv[i] = readInt(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, iv); - --v; - break; - case 'J': - long[] lv = new long[size]; - for (i = 0; i < size; i++) { - lv[i] = readLong(items[readUnsignedShort(v)]); - v += 3; - } - av.visit(name, lv); - --v; - break; - case 'F': - float[] fv = new float[size]; - for (i = 0; i < size; i++) { - fv[i] = Float - .intBitsToFloat(readInt(items[readUnsignedShort(v)])); - v += 3; - } - av.visit(name, fv); - --v; - break; - case 'D': - double[] dv = new double[size]; - for (i = 0; i < size; i++) { - dv[i] = Double - .longBitsToDouble(readLong(items[readUnsignedShort(v)])); - v += 3; - } - av.visit(name, dv); - --v; - break; - default: - v = readAnnotationValues(v - 3, buf, false, av.visitArray(name)); - } - } - return v; - } - - - /** - * Returns the label corresponding to the given offset. The default - * implementation of this method creates a label for the given offset if it - * has not been already created. - * - * @param offset - * a bytecode offset in a method. - * @param labels - * the already created labels, indexed by their offset. If a - * label already exists for offset this method must not create a - * new one. Otherwise it must store the new label in this array. - * @return a non null Label, which must be equal to labels[offset]. - */ - protected Label readLabel(int offset, Label[] labels) { - // SPRING PATCH: leniently handle offset mismatch - if (offset >= labels.length) { - return new Label(); - } - // END OF PATCH - if (labels[offset] == null) { - labels[offset] = new Label(); - } - return labels[offset]; - } - - /** - * Returns the start index of the attribute_info structure of this class. - * - * @return the start index of the attribute_info structure of this class. - */ - private int getAttributes() { - // skips the header - int u = header + 8 + readUnsignedShort(header + 6) * 2; - // skips fields and methods - for (int i = readUnsignedShort(u); i > 0; --i) { - for (int j = readUnsignedShort(u + 8); j > 0; --j) { - u += 6 + readInt(u + 12); - } - u += 8; - } - u += 2; - for (int i = readUnsignedShort(u); i > 0; --i) { - for (int j = readUnsignedShort(u + 8); j > 0; --j) { - u += 6 + readInt(u + 12); - } - u += 8; - } - // the attribute_info structure starts just after the methods - return u + 2; - } - - /** - * Reads an attribute in {@link #b b}. - * - * @param attrs - * prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to - * the type of one the prototypes is ignored (i.e. an empty - * {@link Attribute} instance is returned). - * @param type - * the type of the attribute. - * @param off - * index of the first byte of the attribute's content in - * {@link #b b}. The 6 attribute header bytes, containing the - * type and the length of the attribute, are not taken into - * account here (they have already been read). - * @param len - * the length of the attribute's content. - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param codeOff - * index of the first byte of code's attribute content in - * {@link #b b}, or -1 if the attribute to be read is not a code - * attribute. The 6 attribute header bytes, containing the type - * and the length of the attribute, are not taken into account - * here. - * @param labels - * the labels of the method's code, or null if the - * attribute to be read is not a code attribute. - * @return the attribute that has been read, or null to skip this - * attribute. - */ - private Attribute readAttribute(final Attribute[] attrs, final String type, - final int off, final int len, final char[] buf, final int codeOff, - final Label[] labels) { - for (int i = 0; i < attrs.length; ++i) { - if (attrs[i].type.equals(type)) { - return attrs[i].read(this, off, len, buf, codeOff, labels); - } - } - return new Attribute(type).read(this, off, len, null, -1, null); - } - - - /** - * Reads a byte value in {@link #b b}. This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public int readByte(final int index) { - return b[index] & 0xFF; - } - - /** - * Reads an unsigned short value in {@link #b b}. This method is intended - * for {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public int readUnsignedShort(final int index) { - byte[] b = this.b; - return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); - } - - /** - * Reads a signed short value in {@link #b b}. This method is intended - * for {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public short readShort(final int index) { - byte[] b = this.b; - return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); - } - - /** - * Reads a signed int value in {@link #b b}. This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public int readInt(final int index) { - byte[] b = this.b; - return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) - | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); - } - - /** - * Reads a signed long value in {@link #b b}. This method is intended for - * {@link Attribute} sub classes, and is normally not needed by class - * generators or adapters. - * - * @param index - * the start index of the value to be read in {@link #b b}. - * @return the read value. - */ - public long readLong(final int index) { - long l1 = readInt(index); - long l0 = readInt(index + 4) & 0xFFFFFFFFL; - return (l1 << 32) | l0; - } - - /** - * Reads an UTF8 string constant pool item in {@link #b b}. This method - * is intended for {@link Attribute} sub classes, and is normally not needed - * by class generators or adapters. - * - * @param index - * the start index of an unsigned short value in {@link #b b}, - * whose value is the index of an UTF8 constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the String corresponding to the specified UTF8 item. - */ - public String readUTF8(int index, final char[] buf) { - int item = readUnsignedShort(index); - if (index == 0 || item == 0) { - return null; - } - String s = strings[item]; - if (s != null) { - return s; - } - index = items[item]; - return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf); - } - - /** - * Reads UTF8 string in {@link #b b}. - * - * @param index - * start offset of the UTF8 string to be read. - * @param utfLen - * length of the UTF8 string to be read. - * @param buf - * buffer to be used to read the string. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the String corresponding to the specified UTF8 string. - */ - private String readUTF(int index, final int utfLen, final char[] buf) { - int endIndex = index + utfLen; - byte[] b = this.b; - int strLen = 0; - int c; - int st = 0; - char cc = 0; - while (index < endIndex) { - c = b[index++]; - switch (st) { - case 0: - c = c & 0xFF; - if (c < 0x80) { // 0xxxxxxx - buf[strLen++] = (char) c; - } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx - cc = (char) (c & 0x1F); - st = 1; - } else { // 1110 xxxx 10xx xxxx 10xx xxxx - cc = (char) (c & 0x0F); - st = 2; - } - break; - - case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char - buf[strLen++] = (char) ((cc << 6) | (c & 0x3F)); - st = 0; - break; - - case 2: // byte 2 of 3-byte char - cc = (char) ((cc << 6) | (c & 0x3F)); - st = 1; - break; - } - } - return new String(buf, 0, strLen); - } - - /** - * Reads a class constant pool item in {@link #b b}. This method is - * intended for {@link Attribute} sub classes, and is normally not needed by - * class generators or adapters. - * - * @param index - * the start index of an unsigned short value in {@link #b b}, - * whose value is the index of a class constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the String corresponding to the specified class item. - */ - public String readClass(final int index, final char[] buf) { - // computes the start index of the CONSTANT_Class item in b - // and reads the CONSTANT_Utf8 item designated by - // the first two bytes of this CONSTANT_Class item - return readUTF8(items[readUnsignedShort(index)], buf); - } - - /** - * Reads a numeric or string constant pool item in {@link #b b}. This - * method is intended for {@link Attribute} sub classes, and is normally not - * needed by class generators or adapters. - * - * @param item - * the index of a constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. - * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, - * {@link String}, {@link Type} or {@link Handle} corresponding to - * the given constant pool item. - */ - public Object readConst(final int item, final char[] buf) { - int index = items[item]; - switch (b[index - 1]) { - case INT: - return readInt(index); - case FLOAT: - return Float.intBitsToFloat(readInt(index)); - case LONG: - return readLong(index); - case DOUBLE: - return Double.longBitsToDouble(readLong(index)); - case CLASS: - return Type.getObjectType(readUTF8(index, buf)); - case STR: - return readUTF8(index, buf); - case MTYPE: - return Type.getMethodType(readUTF8(index, buf)); - default: // case ClassWriter.HANDLE_BASE + [1..9]: - int tag = readByte(index); - int[] items = this.items; - int cpIndex = items[readUnsignedShort(index + 1)]; - String owner = readClass(cpIndex, buf); - cpIndex = items[readUnsignedShort(cpIndex + 2)]; - String name = readUTF8(cpIndex, buf); - String desc = readUTF8(cpIndex + 2, buf); - return new Handle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE); - } - } -} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java deleted file mode 100644 index 2ad9692aa05..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java +++ /dev/null @@ -1,146 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.apache.grails.common.compiler.asm; - -import org.springframework.asm.Label; - -/** - * Information about a class being parsed in a {@link ClassReader}. - * - * @author Eric Bruneton - */ -class Context { - - /** - * Prototypes of the attributes that must be parsed for this class. - */ - Attribute[] attrs; - - /** - * The {@link ClassReader} option flags for the parsing of this class. - */ - int flags; - - /** - * The buffer used to read strings. - */ - char[] buffer; - - /** - * The start index of each bootstrap method. - */ - int[] bootstrapMethods; - - /** - * The access flags of the method currently being parsed. - */ - int access; - - /** - * The name of the method currently being parsed. - */ - String name; - - /** - * The descriptor of the method currently being parsed. - */ - String desc; - - /** - * The label objects, indexed by bytecode offset, of the method currently - * being parsed (only bytecode offsets for which a label is needed have a - * non null associated Label object). - */ - Label[] labels; - - /** - * The target of the type annotation currently being parsed. - */ - int typeRef; - - /** - * The path of the type annotation currently being parsed. - */ - TypePath typePath; - - /** - * The offset of the latest stack map frame that has been parsed. - */ - int offset; - - /** - * The labels corresponding to the start of the local variable ranges in the - * local variable type annotation currently being parsed. - */ - Label[] start; - - /** - * The labels corresponding to the end of the local variable ranges in the - * local variable type annotation currently being parsed. - */ - Label[] end; - - /** - * The local variable indices for each local variable range in the local - * variable type annotation currently being parsed. - */ - int[] index; - - /** - * The encoding of the latest stack map frame that has been parsed. - */ - int mode; - - /** - * The number of locals in the latest stack map frame that has been parsed. - */ - int localCount; - - /** - * The number locals in the latest stack map frame that has been parsed, - * minus the number of locals in the previous frame. - */ - int localDiff; - - /** - * The local values of the latest stack map frame that has been parsed. - */ - Object[] local; - - /** - * The stack size of the latest stack map frame that has been parsed. - */ - int stackCount; - - /** - * The stack values of the latest stack map frame that has been parsed. - */ - Object[] stack; -} \ No newline at end of file diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java deleted file mode 100644 index f2510b12aac..00000000000 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java +++ /dev/null @@ -1,196 +0,0 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.apache.grails.common.compiler.asm; - - -/** - * The path to a type argument, wildcard bound, array element type, or static - * inner type within an enclosing type. - * - * @author Eric Bruneton - */ -class TypePath { - - /** - * A type path step that steps into the element type of an array type. See - * {@link #getStep getStep}. - */ - public final static int ARRAY_ELEMENT = 0; - - /** - * A type path step that steps into the nested type of a class type. See - * {@link #getStep getStep}. - */ - public final static int INNER_TYPE = 1; - - /** - * A type path step that steps into the bound of a wildcard type. See - * {@link #getStep getStep}. - */ - public final static int WILDCARD_BOUND = 2; - - /** - * A type path step that steps into a type argument of a generic type. See - * {@link #getStep getStep}. - */ - public final static int TYPE_ARGUMENT = 3; - - /** - * The byte array where the path is stored, in Java class file format. - */ - byte[] b; - - /** - * The offset of the first byte of the type path in 'b'. - */ - int offset; - - /** - * Creates a new type path. - * - * @param b - * the byte array containing the type path in Java class file - * format. - * @param offset - * the offset of the first byte of the type path in 'b'. - */ - TypePath(byte[] b, int offset) { - this.b = b; - this.offset = offset; - } - - /** - * Returns the length of this path. - * - * @return the length of this path. - */ - public int getLength() { - return b[offset]; - } - - /** - * Returns the value of the given step of this path. - * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. - * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE - * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or - * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. - */ - public int getStep(int index) { - return b[offset + 2 * index + 1]; - } - - /** - * Returns the index of the type argument that the given step is stepping - * into. This method should only be used for steps whose value is - * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. - * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. - * @return the index of the type argument that the given step is stepping - * into. - */ - public int getStepArgument(int index) { - return b[offset + 2 * index + 2]; - } - - /** - * Converts a type path in string form, in the format used by - * {@link #toString()}, into a TypePath object. - * - * @param typePath - * a type path in string form, in the format used by - * {@link #toString()}. May be null or empty. - * @return the corresponding TypePath object, or null if the path is empty. - */ - public static TypePath fromString(final String typePath) { - if (typePath == null || typePath.length() == 0) { - return null; - } - int n = typePath.length(); - ByteVector out = new ByteVector(n); - out.putByte(0); - for (int i = 0; i < n;) { - char c = typePath.charAt(i++); - if (c == '[') { - out.put11(ARRAY_ELEMENT, 0); - } else if (c == '.') { - out.put11(INNER_TYPE, 0); - } else if (c == '*') { - out.put11(WILDCARD_BOUND, 0); - } else if (c >= '0' && c <= '9') { - int typeArg = c - '0'; - while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') { - typeArg = typeArg * 10 + c - '0'; - i += 1; - } - if (i < n && typePath.charAt(i) == ';') { - i += 1; - } - out.put11(TYPE_ARGUMENT, typeArg); - } - } - out.data[0] = (byte) (out.length / 2); - return new TypePath(out.data, 0); - } - - /** - * Returns a string representation of this type path. {@link #ARRAY_ELEMENT - * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE - * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps - * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type - * argument index in decimal form followed by ';'. - */ - @Override - public String toString() { - int length = getLength(); - StringBuilder result = new StringBuilder(length * 2); - for (int i = 0; i < length; ++i) { - switch (getStep(i)) { - case ARRAY_ELEMENT: - result.append('['); - break; - case INNER_TYPE: - result.append('.'); - break; - case WILDCARD_BOUND: - result.append('*'); - break; - case TYPE_ARGUMENT: - result.append(getStepArgument(i)).append(';'); - break; - default: - result.append('_'); - } - } - return result.toString(); - } -} diff --git a/grails-common/src/main/resources/META-INF/LICENSE b/grails-common/src/main/resources/META-INF/LICENSE deleted file mode 100644 index 9f2db4a21e3..00000000000 --- a/grails-common/src/main/resources/META-INF/LICENSE +++ /dev/null @@ -1,233 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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 - - https://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. - --------------------------------------------------------------------------- - -BSD License - -The following classes within this product: - - org.apache.grails.common.compiler.asm.Attribute - org.apache.grails.common.compiler.asm.ByteVector - org.apache.grails.common.compiler.asm.ClassReader - org.apache.grails.common.compiler.asm.Context - org.apache.grails.common.compiler.asm.TypePath - -See the LICENSE/licenses-asm.txt file for the ASM license terms. - --------------------------------------------------------------------------- - -This product includes the following classes from Spring Framework 5.3, developed by Pivotal Software, Inc., licensed under the Apache License 2.0: - - org.apache.grails.common.annotation.AbstractRecursiveAnnotationVisitor - org.apache.grails.common.annotation.AnnotationAttributesReadingVisitor - org.apache.grails.common.annotation.AnnotationMetadataReadingVisitor - org.apache.grails.common.annotation.AnnotationReadingVisitorUtils - org.apache.grails.common.annotation.ClassMetadataReadingVisitor - org.apache.grails.common.annotation.MethodMetadataReadingVisitor - org.apache.grails.common.annotation.RecursiveAnnotationArrayVisitor - org.apache.grails.common.annotation.RecursiveAnnotationAttributesVisitor - -See the above Apache License 2.0 for the terms governing these files. - --------------------------------------------------------------------------- \ No newline at end of file diff --git a/grails-common/src/main/resources/META-INF/NOTICE b/grails-common/src/main/resources/META-INF/NOTICE deleted file mode 100644 index d524ab7e3e7..00000000000 --- a/grails-common/src/main/resources/META-INF/NOTICE +++ /dev/null @@ -1,18 +0,0 @@ -Apache Grails -Copyright 2005-2025 The Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). - - -Additional Licenses ------------------- - -ASM Library -This product includes software from ASM Library, licensed under BSD License. -Copyright 2000-2011 INRIA, France Telecom. -See licenses/LICENSE-asm.txt for the full license terms. - -This product includes software from Spring Framework 5.3, developed by Pivotal Software, Inc. -Copyright 2002-2020 the original author or authors. -See the LICENSE file for the Apache License 2.0 terms. \ No newline at end of file diff --git a/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy b/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy index 88fc29a66bd..8691eaf698c 100644 --- a/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy +++ b/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy @@ -22,11 +22,11 @@ import groovy.transform.CompileStatic import groovy.transform.InheritConstructors import groovy.transform.Memoized import groovy.util.logging.Slf4j -import org.apache.grails.common.compiler.asm.AnnotationMetadataReader import org.springframework.core.io.DefaultResourceLoader import org.springframework.core.io.Resource import org.springframework.core.io.support.PathMatchingResourcePatternResolver import org.springframework.core.io.support.ResourcePatternResolver +import org.springframework.core.type.classreading.SimpleMetadataReaderFactory import org.springframework.util.ClassUtils import java.lang.annotation.Annotation @@ -173,10 +173,12 @@ class ClassPathScanner { private void scanUsingPattern(ResourcePatternResolver resourcePatternResolver, String pattern, ClassLoader classLoader, Closure annotationFilter, Set classes) { def resources = resourcePatternResolver.getResources(pattern) + + def factory = new SimpleMetadataReaderFactory(classLoader) for (Resource res in resources) { // ignore closures / inner classes if (!isExcluded(res)) { - def reader = new AnnotationMetadataReader(res, classLoader) + def reader = factory.getMetadataReader(res) def metadata = reader.annotationMetadata if (metadata.annotationTypes.any(annotationFilter)) { classes << classLoader.loadClass(reader.classMetadata.className) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java deleted file mode 100644 index 78b29ec5298..00000000000 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * https://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.grails.datastore.gorm.utils; - -import org.apache.grails.common.compiler.asm.AnnotationMetadataReader; -import org.springframework.core.io.Resource; -import org.springframework.core.type.classreading.CachingMetadataReaderFactory; -import org.springframework.core.type.classreading.MetadataReader; - -import java.io.IOException; - -/** - * A {@link CachingMetadataReaderFactory} that only reads annotations and not the whole class body - */ -class AnnotationMetadataReaderFactory extends CachingMetadataReaderFactory { - public AnnotationMetadataReaderFactory(ClassLoader classLoader) { - super(classLoader); - } - - @Override - public MetadataReader getMetadataReader(Resource resource) throws IOException { - return new AnnotationMetadataReader(resource, getResourceLoader().getClassLoader(), false); - } -} diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy index c39a25c10d1..b180ea815d4 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy @@ -24,6 +24,7 @@ import groovy.util.logging.Slf4j import org.grails.datastore.mapping.reflect.ClassUtils import org.springframework.beans.factory.config.BeanDefinition import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider +import org.springframework.core.type.classreading.SimpleMetadataReaderFactory import org.springframework.core.type.filter.AnnotationTypeFilter import java.lang.annotation.Annotation @@ -70,7 +71,7 @@ class ClasspathEntityScanner { */ Class[] scan(Package... packages) { ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(false) - componentProvider.setMetadataReaderFactory(new AnnotationMetadataReaderFactory(classLoader)) + componentProvider.setMetadataReaderFactory(new SimpleMetadataReaderFactory(classLoader)) for(ann in annotations) { componentProvider.addIncludeFilter(new AnnotationTypeFilter(ann)) } diff --git a/licenses/LICENSE-asm.txt b/licenses/LICENSE-asm.txt deleted file mode 100644 index 1a71c4ce466..00000000000 --- a/licenses/LICENSE-asm.txt +++ /dev/null @@ -1,27 +0,0 @@ -ASM: a very small and fast Java bytecode manipulation framework -Copyright (c) 2000-2011 INRIA, France Telecom -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holders nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -THE POSSIBILITY OF SUCH DAMAGE.