mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-09 10:01:41 +01:00
8301269: Update Commons BCEL to Version 6.7.0
Reviewed-by: mdoerr
Backport-of: 6a44120a16
This commit is contained in:
committed by
Vitaly Provodin
parent
5c781b4a20
commit
db41c86372
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -20,13 +20,24 @@
|
||||
|
||||
package com.sun.org.apache.bcel.internal;
|
||||
|
||||
import jdk.xml.internal.Utils;
|
||||
|
||||
/**
|
||||
* Exception constants.
|
||||
*
|
||||
* @since 6.0 (intended to replace the InstructionConstant interface)
|
||||
* @LastModified: May 2021
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public final class ExceptionConst {
|
||||
|
||||
/**
|
||||
* Enum corresponding to the various Exception Class arrays, used by
|
||||
* {@link ExceptionConst#createExceptions(EXCS, Class...)}
|
||||
*/
|
||||
public enum EXCS {
|
||||
EXCS_CLASS_AND_INTERFACE_RESOLUTION, EXCS_FIELD_AND_METHOD_RESOLUTION, EXCS_INTERFACE_METHOD_RESOLUTION, EXCS_STRING_RESOLUTION, EXCS_ARRAY_EXCEPTION,
|
||||
}
|
||||
|
||||
/**
|
||||
* The mother of all exceptions
|
||||
*/
|
||||
@@ -64,61 +75,41 @@ public final class ExceptionConst {
|
||||
* Run-Time Exceptions
|
||||
*/
|
||||
public static final Class<NullPointerException> NULL_POINTER_EXCEPTION = NullPointerException.class;
|
||||
public static final Class<ArrayIndexOutOfBoundsException> ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION
|
||||
= ArrayIndexOutOfBoundsException.class;
|
||||
public static final Class<ArrayIndexOutOfBoundsException> ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class;
|
||||
public static final Class<ArithmeticException> ARITHMETIC_EXCEPTION = ArithmeticException.class;
|
||||
public static final Class<NegativeArraySizeException> NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class;
|
||||
public static final Class<ClassCastException> CLASS_CAST_EXCEPTION = ClassCastException.class;
|
||||
|
||||
public static final Class<IllegalMonitorStateException> ILLEGAL_MONITOR_STATE = IllegalMonitorStateException.class;
|
||||
/**
|
||||
* Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual Machine Specification
|
||||
*/
|
||||
private static final Class<?>[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = {NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR,
|
||||
EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR}; // Chapter 5.1
|
||||
|
||||
private static final Class<?>[] EXCS_FIELD_AND_METHOD_RESOLUTION = {NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR}; // Chapter 5.2
|
||||
|
||||
/**
|
||||
* Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual
|
||||
* Machine Specification
|
||||
* Empty array.
|
||||
*/
|
||||
private static final Class<?>[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = {
|
||||
NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR,
|
||||
EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR
|
||||
}; // Chapter 5.1
|
||||
private static final Class<?>[] EXCS_FIELD_AND_METHOD_RESOLUTION = {
|
||||
NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR
|
||||
}; // Chapter 5.2
|
||||
private static final Class<?>[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class<?>[0]; // Chapter 5.3 (as below)
|
||||
private static final Class<?>[] EXCS_STRING_RESOLUTION = new Class<?>[0];
|
||||
// Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.)
|
||||
private static final Class<?>[] EXCS_ARRAY_EXCEPTION = {
|
||||
NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION
|
||||
};
|
||||
|
||||
/**
|
||||
* Enum corresponding to the various Exception Class arrays,
|
||||
* used by {@link ExceptionConst#createExceptions(EXCS, Class...)}
|
||||
* Empty array.
|
||||
*/
|
||||
public enum EXCS {
|
||||
EXCS_CLASS_AND_INTERFACE_RESOLUTION,
|
||||
EXCS_FIELD_AND_METHOD_RESOLUTION,
|
||||
EXCS_INTERFACE_METHOD_RESOLUTION,
|
||||
EXCS_STRING_RESOLUTION,
|
||||
EXCS_ARRAY_EXCEPTION,
|
||||
}
|
||||
private static final Class<?>[] EXCS_STRING_RESOLUTION = new Class<?>[0];
|
||||
|
||||
// helper method to merge exception class arrays
|
||||
private static Class<?>[] mergeExceptions(final Class<?>[] input, final Class<?> ... extraClasses) {
|
||||
final int extraLen = extraClasses == null ? 0 : extraClasses.length;
|
||||
final Class<?>[] excs = new Class<?>[input.length + extraLen];
|
||||
System.arraycopy(input, 0, excs, 0, input.length);
|
||||
if (extraLen > 0) {
|
||||
System.arraycopy(extraClasses, 0, excs, input.length, extraLen);
|
||||
}
|
||||
return excs;
|
||||
}
|
||||
// Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.)
|
||||
private static final Class<?>[] EXCS_ARRAY_EXCEPTION = {NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION};
|
||||
|
||||
/**
|
||||
* Creates a copy of the specified Exception Class array combined with any additional Exception classes.
|
||||
*
|
||||
* @param type the basic array type
|
||||
* @param extraClasses additional classes, if any
|
||||
* @return the merged array
|
||||
*/
|
||||
public static Class<?>[] createExceptions(final EXCS type, final Class<?> ... extraClasses) {
|
||||
public static Class<?>[] createExceptions(final EXCS type, final Class<?>... extraClasses) {
|
||||
switch (type) {
|
||||
case EXCS_CLASS_AND_INTERFACE_RESOLUTION:
|
||||
return mergeExceptions(EXCS_CLASS_AND_INTERFACE_RESOLUTION, extraClasses);
|
||||
@@ -135,5 +126,8 @@ public final class ExceptionConst {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper method to merge exception class arrays
|
||||
private static Class<?>[] mergeExceptions(final Class<?>[] input, final Class<?>... extraClasses) {
|
||||
return Utils.arraysAppend(input, extraClasses);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -24,20 +24,54 @@ import com.sun.org.apache.bcel.internal.classfile.JavaClass;
|
||||
import com.sun.org.apache.bcel.internal.util.SyntheticRepository;
|
||||
|
||||
/**
|
||||
* The repository maintains informations about class interdependencies, e.g.,
|
||||
* whether a class is a sub-class of another. Delegates actual class loading
|
||||
* to SyntheticRepository with current class path by default.
|
||||
* The repository maintains informations about class interdependencies, e.g., whether a class is a sub-class of another.
|
||||
* Delegates actual class loading to SyntheticRepository with current class path by default.
|
||||
*
|
||||
* @see com.sun.org.apache.bcel.internal.util.Repository
|
||||
* @see SyntheticRepository
|
||||
*
|
||||
* @LastModified: Jan 2020
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public abstract class Repository {
|
||||
|
||||
private static com.sun.org.apache.bcel.internal.util.Repository repository
|
||||
= SyntheticRepository.getInstance();
|
||||
private static com.sun.org.apache.bcel.internal.util.Repository repository = SyntheticRepository.getInstance();
|
||||
|
||||
/**
|
||||
* Adds clazz to repository if there isn't an equally named class already in there.
|
||||
*
|
||||
* @return old entry in repository
|
||||
*/
|
||||
public static JavaClass addClass(final JavaClass clazz) {
|
||||
final JavaClass old = repository.findClass(clazz.getClassName());
|
||||
repository.storeClass(clazz);
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the repository.
|
||||
*/
|
||||
public static void clearCache() {
|
||||
repository.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all interfaces implemented by class and its super classes and the interfaces that those interfaces extend,
|
||||
* and so on. (Some people call this a transitive hull).
|
||||
* @throws ClassNotFoundException if any of the class's superclasses or superinterfaces can't be found
|
||||
*/
|
||||
public static JavaClass[] getInterfaces(final JavaClass clazz) throws ClassNotFoundException {
|
||||
return clazz.getAllInterfaces();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all interfaces implemented by class and its super classes and the interfaces that extend those interfaces,
|
||||
* and so on
|
||||
* @throws ClassNotFoundException if the named class can't be found, or if any of its superclasses or superinterfaces
|
||||
* can't be found
|
||||
*/
|
||||
public static JavaClass[] getInterfaces(final String className) throws ClassNotFoundException {
|
||||
return getInterfaces(lookupClass(className));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return currently used repository instance
|
||||
@@ -46,205 +80,127 @@ public abstract class Repository {
|
||||
return repository;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets repository instance to be used for class loading
|
||||
* @return list of super classes of clazz in ascending order, i.e., Object is always the last element
|
||||
* @throws ClassNotFoundException if any of the superclasses can't be found
|
||||
*/
|
||||
public static void setRepository( final com.sun.org.apache.bcel.internal.util.Repository rep ) {
|
||||
repository = rep;
|
||||
public static JavaClass[] getSuperClasses(final JavaClass clazz) throws ClassNotFoundException {
|
||||
return clazz.getSuperClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of super classes of clazz in ascending order, i.e., Object is always the last element.
|
||||
* @throws ClassNotFoundException if the named class or any of its superclasses can't be found
|
||||
*/
|
||||
public static JavaClass[] getSuperClasses(final String className) throws ClassNotFoundException {
|
||||
return getSuperClasses(lookupClass(className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookups class somewhere found on your CLASSPATH, or whereever the
|
||||
* repository instance looks for it.
|
||||
* @return true, if clazz is an implementation of interface inter
|
||||
* @throws ClassNotFoundException if any superclasses or superinterfaces of clazz can't be found
|
||||
*/
|
||||
public static boolean implementationOf(final JavaClass clazz, final JavaClass inter) throws ClassNotFoundException {
|
||||
return clazz.implementationOf(inter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an implementation of interface inter
|
||||
* @throws ClassNotFoundException if inter or any superclasses or superinterfaces of clazz can't be found
|
||||
*/
|
||||
public static boolean implementationOf(final JavaClass clazz, final String inter) throws ClassNotFoundException {
|
||||
return implementationOf(clazz, lookupClass(inter));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an implementation of interface inter
|
||||
* @throws ClassNotFoundException if clazz or any superclasses or superinterfaces of clazz can't be found
|
||||
*/
|
||||
public static boolean implementationOf(final String clazz, final JavaClass inter) throws ClassNotFoundException {
|
||||
return implementationOf(lookupClass(clazz), inter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an implementation of interface inter
|
||||
* @throws ClassNotFoundException if clazz, inter, or any superclasses or superinterfaces of clazz can't be found
|
||||
*/
|
||||
public static boolean implementationOf(final String clazz, final String inter) throws ClassNotFoundException {
|
||||
return implementationOf(lookupClass(clazz), lookupClass(inter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to runtime "instanceof" operator.
|
||||
*
|
||||
* @return class object for given fully qualified class name
|
||||
* @throws ClassNotFoundException if the class could not be found or
|
||||
* parsed correctly
|
||||
* @return true, if clazz is an instance of superclass
|
||||
* @throws ClassNotFoundException if any superclasses or superinterfaces of clazz can't be found
|
||||
*/
|
||||
public static JavaClass lookupClass( final String class_name ) throws ClassNotFoundException {
|
||||
return repository.loadClass(class_name);
|
||||
public static boolean instanceOf(final JavaClass clazz, final JavaClass superclass) throws ClassNotFoundException {
|
||||
return clazz.instanceOf(superclass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an instance of superclass
|
||||
* @throws ClassNotFoundException if superclass can't be found
|
||||
*/
|
||||
public static boolean instanceOf(final JavaClass clazz, final String superclass) throws ClassNotFoundException {
|
||||
return instanceOf(clazz, lookupClass(superclass));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an instance of superclass
|
||||
* @throws ClassNotFoundException if clazz can't be found
|
||||
*/
|
||||
public static boolean instanceOf(final String clazz, final JavaClass superclass) throws ClassNotFoundException {
|
||||
return instanceOf(lookupClass(clazz), superclass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an instance of superclass
|
||||
* @throws ClassNotFoundException if either clazz or superclass can't be found
|
||||
*/
|
||||
public static boolean instanceOf(final String clazz, final String superclass) throws ClassNotFoundException {
|
||||
return instanceOf(lookupClass(clazz), lookupClass(superclass));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find class source using the internal repository instance.
|
||||
*
|
||||
* @see Class
|
||||
* @return JavaClass object for given runtime class
|
||||
* @throws ClassNotFoundException if the class could not be found or
|
||||
* parsed correctly
|
||||
* @throws ClassNotFoundException if the class could not be found or parsed correctly
|
||||
*/
|
||||
public static JavaClass lookupClass( final Class<?> clazz ) throws ClassNotFoundException {
|
||||
public static JavaClass lookupClass(final Class<?> clazz) throws ClassNotFoundException {
|
||||
return repository.loadClass(clazz);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the repository.
|
||||
*/
|
||||
public static void clearCache() {
|
||||
repository.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds clazz to repository if there isn't an equally named class already in there.
|
||||
* Lookups class somewhere found on your CLASSPATH, or wherever the repository instance looks for it.
|
||||
*
|
||||
* @return old entry in repository
|
||||
* @return class object for given fully qualified class name
|
||||
* @throws ClassNotFoundException if the class could not be found or parsed correctly
|
||||
*/
|
||||
public static JavaClass addClass( final JavaClass clazz ) {
|
||||
final JavaClass old = repository.findClass(clazz.getClassName());
|
||||
repository.storeClass(clazz);
|
||||
return old;
|
||||
public static JavaClass lookupClass(final String className) throws ClassNotFoundException {
|
||||
return repository.loadClass(className);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes class with given (fully qualified) name from repository.
|
||||
*/
|
||||
public static void removeClass( final String clazz ) {
|
||||
repository.removeClass(repository.findClass(clazz));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes given class from repository.
|
||||
*/
|
||||
public static void removeClass( final JavaClass clazz ) {
|
||||
public static void removeClass(final JavaClass clazz) {
|
||||
repository.removeClass(clazz);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return list of super classes of clazz in ascending order, i.e.,
|
||||
* Object is always the last element
|
||||
* @throws ClassNotFoundException if any of the superclasses can't be found
|
||||
* Removes class with given (fully qualified) name from repository.
|
||||
*/
|
||||
public static JavaClass[] getSuperClasses( final JavaClass clazz ) throws ClassNotFoundException {
|
||||
return clazz.getSuperClasses();
|
||||
public static void removeClass(final String clazz) {
|
||||
repository.removeClass(repository.findClass(clazz));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return list of super classes of clazz in ascending order, i.e.,
|
||||
* Object is always the last element.
|
||||
* @throws ClassNotFoundException if the named class or any of its
|
||||
* superclasses can't be found
|
||||
* Sets repository instance to be used for class loading
|
||||
*/
|
||||
public static JavaClass[] getSuperClasses( final String class_name ) throws ClassNotFoundException {
|
||||
final JavaClass jc = lookupClass(class_name);
|
||||
return getSuperClasses(jc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return all interfaces implemented by class and its super
|
||||
* classes and the interfaces that those interfaces extend, and so on.
|
||||
* (Some people call this a transitive hull).
|
||||
* @throws ClassNotFoundException if any of the class's
|
||||
* superclasses or superinterfaces can't be found
|
||||
*/
|
||||
public static JavaClass[] getInterfaces( final JavaClass clazz ) throws ClassNotFoundException {
|
||||
return clazz.getAllInterfaces();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return all interfaces implemented by class and its super
|
||||
* classes and the interfaces that extend those interfaces, and so on
|
||||
* @throws ClassNotFoundException if the named class can't be found,
|
||||
* or if any of its superclasses or superinterfaces can't be found
|
||||
*/
|
||||
public static JavaClass[] getInterfaces( final String class_name ) throws ClassNotFoundException {
|
||||
return getInterfaces(lookupClass(class_name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Equivalent to runtime "instanceof" operator.
|
||||
* @return true, if clazz is an instance of super_class
|
||||
* @throws ClassNotFoundException if any superclasses or superinterfaces
|
||||
* of clazz can't be found
|
||||
*/
|
||||
public static boolean instanceOf( final JavaClass clazz, final JavaClass super_class )
|
||||
throws ClassNotFoundException {
|
||||
return clazz.instanceOf(super_class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an instance of super_class
|
||||
* @throws ClassNotFoundException if either clazz or super_class
|
||||
* can't be found
|
||||
*/
|
||||
public static boolean instanceOf( final String clazz, final String super_class )
|
||||
throws ClassNotFoundException {
|
||||
return instanceOf(lookupClass(clazz), lookupClass(super_class));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an instance of super_class
|
||||
* @throws ClassNotFoundException if super_class can't be found
|
||||
*/
|
||||
public static boolean instanceOf( final JavaClass clazz, final String super_class )
|
||||
throws ClassNotFoundException {
|
||||
return instanceOf(clazz, lookupClass(super_class));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an instance of super_class
|
||||
* @throws ClassNotFoundException if clazz can't be found
|
||||
*/
|
||||
public static boolean instanceOf( final String clazz, final JavaClass super_class )
|
||||
throws ClassNotFoundException {
|
||||
return instanceOf(lookupClass(clazz), super_class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an implementation of interface inter
|
||||
* @throws ClassNotFoundException if any superclasses or superinterfaces
|
||||
* of clazz can't be found
|
||||
*/
|
||||
public static boolean implementationOf( final JavaClass clazz, final JavaClass inter )
|
||||
throws ClassNotFoundException {
|
||||
return clazz.implementationOf(inter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an implementation of interface inter
|
||||
* @throws ClassNotFoundException if clazz, inter, or any superclasses
|
||||
* or superinterfaces of clazz can't be found
|
||||
*/
|
||||
public static boolean implementationOf( final String clazz, final String inter )
|
||||
throws ClassNotFoundException {
|
||||
return implementationOf(lookupClass(clazz), lookupClass(inter));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an implementation of interface inter
|
||||
* @throws ClassNotFoundException if inter or any superclasses
|
||||
* or superinterfaces of clazz can't be found
|
||||
*/
|
||||
public static boolean implementationOf( final JavaClass clazz, final String inter )
|
||||
throws ClassNotFoundException {
|
||||
return implementationOf(clazz, lookupClass(inter));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true, if clazz is an implementation of interface inter
|
||||
* @throws ClassNotFoundException if clazz or any superclasses or
|
||||
* superinterfaces of clazz can't be found
|
||||
*/
|
||||
public static boolean implementationOf( final String clazz, final JavaClass inter )
|
||||
throws ClassNotFoundException {
|
||||
return implementationOf(lookupClass(clazz), inter);
|
||||
public static void setRepository(final com.sun.org.apache.bcel.internal.util.Repository rep) {
|
||||
repository = rep;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,14 +29,17 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
*/
|
||||
public abstract class AccessFlags {
|
||||
|
||||
private int access_flags;
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int access_flags; // TODO not used externally at present
|
||||
|
||||
public AccessFlags() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a
|
||||
* inital access flags
|
||||
* @param a initial access flags
|
||||
*/
|
||||
public AccessFlags(final int a) {
|
||||
access_flags = a;
|
||||
@@ -56,24 +59,141 @@ public abstract class AccessFlags {
|
||||
return access_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set access flags aka "modifiers".
|
||||
*
|
||||
* @param access_flags
|
||||
* Access flags of the object.
|
||||
*/
|
||||
public final void setAccessFlags(final int access_flags) {
|
||||
this.access_flags = access_flags;
|
||||
public final boolean isAbstract() {
|
||||
return (access_flags & Const.ACC_ABSTRACT) != 0;
|
||||
}
|
||||
|
||||
public final void isAbstract(final boolean flag) {
|
||||
setFlag(Const.ACC_ABSTRACT, flag);
|
||||
}
|
||||
|
||||
public final boolean isAnnotation() {
|
||||
return (access_flags & Const.ACC_ANNOTATION) != 0;
|
||||
}
|
||||
|
||||
public final void isAnnotation(final boolean flag) {
|
||||
setFlag(Const.ACC_ANNOTATION, flag);
|
||||
}
|
||||
|
||||
public final boolean isEnum() {
|
||||
return (access_flags & Const.ACC_ENUM) != 0;
|
||||
}
|
||||
|
||||
public final void isEnum(final boolean flag) {
|
||||
setFlag(Const.ACC_ENUM, flag);
|
||||
}
|
||||
|
||||
public final boolean isFinal() {
|
||||
return (access_flags & Const.ACC_FINAL) != 0;
|
||||
}
|
||||
|
||||
public final void isFinal(final boolean flag) {
|
||||
setFlag(Const.ACC_FINAL, flag);
|
||||
}
|
||||
|
||||
public final boolean isInterface() {
|
||||
return (access_flags & Const.ACC_INTERFACE) != 0;
|
||||
}
|
||||
|
||||
public final void isInterface(final boolean flag) {
|
||||
setFlag(Const.ACC_INTERFACE, flag);
|
||||
}
|
||||
|
||||
public final boolean isNative() {
|
||||
return (access_flags & Const.ACC_NATIVE) != 0;
|
||||
}
|
||||
|
||||
public final void isNative(final boolean flag) {
|
||||
setFlag(Const.ACC_NATIVE, flag);
|
||||
}
|
||||
|
||||
public final boolean isPrivate() {
|
||||
return (access_flags & Const.ACC_PRIVATE) != 0;
|
||||
}
|
||||
|
||||
public final void isPrivate(final boolean flag) {
|
||||
setFlag(Const.ACC_PRIVATE, flag);
|
||||
}
|
||||
|
||||
public final boolean isProtected() {
|
||||
return (access_flags & Const.ACC_PROTECTED) != 0;
|
||||
}
|
||||
|
||||
public final void isProtected(final boolean flag) {
|
||||
setFlag(Const.ACC_PROTECTED, flag);
|
||||
}
|
||||
|
||||
public final boolean isPublic() {
|
||||
return (access_flags & Const.ACC_PUBLIC) != 0;
|
||||
}
|
||||
|
||||
public final void isPublic(final boolean flag) {
|
||||
setFlag(Const.ACC_PUBLIC, flag);
|
||||
}
|
||||
|
||||
public final boolean isStatic() {
|
||||
return (access_flags & Const.ACC_STATIC) != 0;
|
||||
}
|
||||
|
||||
public final void isStatic(final boolean flag) {
|
||||
setFlag(Const.ACC_STATIC, flag);
|
||||
}
|
||||
|
||||
public final boolean isStrictfp() {
|
||||
return (access_flags & Const.ACC_STRICT) != 0;
|
||||
}
|
||||
|
||||
public final void isStrictfp(final boolean flag) {
|
||||
setFlag(Const.ACC_STRICT, flag);
|
||||
}
|
||||
|
||||
public final boolean isSynchronized() {
|
||||
return (access_flags & Const.ACC_SYNCHRONIZED) != 0;
|
||||
}
|
||||
|
||||
public final void isSynchronized(final boolean flag) {
|
||||
setFlag(Const.ACC_SYNCHRONIZED, flag);
|
||||
}
|
||||
|
||||
public final boolean isSynthetic() {
|
||||
return (access_flags & Const.ACC_SYNTHETIC) != 0;
|
||||
}
|
||||
|
||||
public final void isSynthetic(final boolean flag) {
|
||||
setFlag(Const.ACC_SYNTHETIC, flag);
|
||||
}
|
||||
|
||||
public final boolean isTransient() {
|
||||
return (access_flags & Const.ACC_TRANSIENT) != 0;
|
||||
}
|
||||
|
||||
public final void isTransient(final boolean flag) {
|
||||
setFlag(Const.ACC_TRANSIENT, flag);
|
||||
}
|
||||
|
||||
public final boolean isVarArgs() {
|
||||
return (access_flags & Const.ACC_VARARGS) != 0;
|
||||
}
|
||||
|
||||
public final void isVarArgs(final boolean flag) {
|
||||
setFlag(Const.ACC_VARARGS, flag);
|
||||
}
|
||||
|
||||
public final boolean isVolatile() {
|
||||
return (access_flags & Const.ACC_VOLATILE) != 0;
|
||||
}
|
||||
|
||||
public final void isVolatile(final boolean flag) {
|
||||
setFlag(Const.ACC_VOLATILE, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set access flags aka "modifiers".
|
||||
*
|
||||
* @param access_flags
|
||||
* Access flags of the object.
|
||||
* @param accessFlags Access flags of the object.
|
||||
*/
|
||||
public final void setModifiers(final int access_flags) {
|
||||
setAccessFlags(access_flags);
|
||||
public final void setAccessFlags(final int accessFlags) {
|
||||
this.access_flags = accessFlags;
|
||||
}
|
||||
|
||||
private void setFlag(final int flag, final boolean set) {
|
||||
@@ -81,138 +201,17 @@ public abstract class AccessFlags {
|
||||
if (!set) {
|
||||
access_flags ^= flag;
|
||||
}
|
||||
} else { // Flag not set
|
||||
if (set) {
|
||||
access_flags |= flag;
|
||||
}
|
||||
} else if (set) {
|
||||
access_flags |= flag;
|
||||
}
|
||||
}
|
||||
|
||||
public final void isPublic(final boolean flag) {
|
||||
setFlag(Const.ACC_PUBLIC, flag);
|
||||
}
|
||||
|
||||
public final boolean isPublic() {
|
||||
return (access_flags & Const.ACC_PUBLIC) != 0;
|
||||
}
|
||||
|
||||
public final void isPrivate(final boolean flag) {
|
||||
setFlag(Const.ACC_PRIVATE, flag);
|
||||
}
|
||||
|
||||
public final boolean isPrivate() {
|
||||
return (access_flags & Const.ACC_PRIVATE) != 0;
|
||||
}
|
||||
|
||||
public final void isProtected(final boolean flag) {
|
||||
setFlag(Const.ACC_PROTECTED, flag);
|
||||
}
|
||||
|
||||
public final boolean isProtected() {
|
||||
return (access_flags & Const.ACC_PROTECTED) != 0;
|
||||
}
|
||||
|
||||
public final void isStatic(final boolean flag) {
|
||||
setFlag(Const.ACC_STATIC, flag);
|
||||
}
|
||||
|
||||
public final boolean isStatic() {
|
||||
return (access_flags & Const.ACC_STATIC) != 0;
|
||||
}
|
||||
|
||||
public final void isFinal(final boolean flag) {
|
||||
setFlag(Const.ACC_FINAL, flag);
|
||||
}
|
||||
|
||||
public final boolean isFinal() {
|
||||
return (access_flags & Const.ACC_FINAL) != 0;
|
||||
}
|
||||
|
||||
public final void isSynchronized(final boolean flag) {
|
||||
setFlag(Const.ACC_SYNCHRONIZED, flag);
|
||||
}
|
||||
|
||||
public final boolean isSynchronized() {
|
||||
return (access_flags & Const.ACC_SYNCHRONIZED) != 0;
|
||||
}
|
||||
|
||||
public final void isVolatile(final boolean flag) {
|
||||
setFlag(Const.ACC_VOLATILE, flag);
|
||||
}
|
||||
|
||||
public final boolean isVolatile() {
|
||||
return (access_flags & Const.ACC_VOLATILE) != 0;
|
||||
}
|
||||
|
||||
public final void isTransient(final boolean flag) {
|
||||
setFlag(Const.ACC_TRANSIENT, flag);
|
||||
}
|
||||
|
||||
public final boolean isTransient() {
|
||||
return (access_flags & Const.ACC_TRANSIENT) != 0;
|
||||
}
|
||||
|
||||
public final void isNative(final boolean flag) {
|
||||
setFlag(Const.ACC_NATIVE, flag);
|
||||
}
|
||||
|
||||
public final boolean isNative() {
|
||||
return (access_flags & Const.ACC_NATIVE) != 0;
|
||||
}
|
||||
|
||||
public final void isInterface(final boolean flag) {
|
||||
setFlag(Const.ACC_INTERFACE, flag);
|
||||
}
|
||||
|
||||
public final boolean isInterface() {
|
||||
return (access_flags & Const.ACC_INTERFACE) != 0;
|
||||
}
|
||||
|
||||
public final void isAbstract(final boolean flag) {
|
||||
setFlag(Const.ACC_ABSTRACT, flag);
|
||||
}
|
||||
|
||||
public final boolean isAbstract() {
|
||||
return (access_flags & Const.ACC_ABSTRACT) != 0;
|
||||
}
|
||||
|
||||
public final void isStrictfp(final boolean flag) {
|
||||
setFlag(Const.ACC_STRICT, flag);
|
||||
}
|
||||
|
||||
public final boolean isStrictfp() {
|
||||
return (access_flags & Const.ACC_STRICT) != 0;
|
||||
}
|
||||
|
||||
public final void isSynthetic(final boolean flag) {
|
||||
setFlag(Const.ACC_SYNTHETIC, flag);
|
||||
}
|
||||
|
||||
public final boolean isSynthetic() {
|
||||
return (access_flags & Const.ACC_SYNTHETIC) != 0;
|
||||
}
|
||||
|
||||
public final void isAnnotation(final boolean flag) {
|
||||
setFlag(Const.ACC_ANNOTATION, flag);
|
||||
}
|
||||
|
||||
public final boolean isAnnotation() {
|
||||
return (access_flags & Const.ACC_ANNOTATION) != 0;
|
||||
}
|
||||
|
||||
public final void isEnum(final boolean flag) {
|
||||
setFlag(Const.ACC_ENUM, flag);
|
||||
}
|
||||
|
||||
public final boolean isEnum() {
|
||||
return (access_flags & Const.ACC_ENUM) != 0;
|
||||
}
|
||||
|
||||
public final void isVarArgs(final boolean flag) {
|
||||
setFlag(Const.ACC_VARARGS, flag);
|
||||
}
|
||||
|
||||
public final boolean isVarArgs() {
|
||||
return (access_flags & Const.ACC_VARARGS) != 0;
|
||||
/**
|
||||
* Set access flags aka "modifiers".
|
||||
*
|
||||
* @param accessFlags Access flags of the object.
|
||||
*/
|
||||
public final void setModifiers(final int accessFlags) {
|
||||
setAccessFlags(accessFlags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* Represents the default value of a annotation for a method info
|
||||
* Represents the default value of a annotation for a method info.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
@@ -37,31 +37,30 @@ public class AnnotationDefault extends Attribute {
|
||||
private ElementValue defaultValue;
|
||||
|
||||
/**
|
||||
* @param name_index Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
AnnotationDefault(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
this(name_index, length, (ElementValue) null, constant_pool);
|
||||
defaultValue = ElementValue.readElementValue(input, constant_pool);
|
||||
AnnotationDefault(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (ElementValue) null, constantPool);
|
||||
defaultValue = ElementValue.readElementValue(input, constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name_index Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param defaultValue the annotation's default value
|
||||
* @param constant_pool Array of constants
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param defaultValue the annotation's default value
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public AnnotationDefault(final int name_index, final int length, final ElementValue defaultValue, final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_ANNOTATION_DEFAULT, name_index, length, constant_pool);
|
||||
public AnnotationDefault(final int nameIndex, final int length, final ElementValue defaultValue, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_ANNOTATION_DEFAULT, nameIndex, length, constantPool);
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@@ -70,11 +69,15 @@ public class AnnotationDefault extends Attribute {
|
||||
v.visitAnnotationDefault(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defaultValue the default value of this methodinfo's annotation
|
||||
*/
|
||||
public final void setDefaultValue(final ElementValue defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void dump(final DataOutputStream dos) throws IOException {
|
||||
super.dump(dos);
|
||||
defaultValue.dump(dos);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,14 +87,10 @@ public class AnnotationDefault extends Attribute {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool _constant_pool) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void dump(final DataOutputStream dos) throws IOException {
|
||||
super.dump(dos);
|
||||
defaultValue.dump(dos);
|
||||
/**
|
||||
* @param defaultValue the default value of this methodinfo's annotation
|
||||
*/
|
||||
public final void setDefaultValue(final ElementValue defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,43 +27,35 @@ import java.io.IOException;
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
public class AnnotationElementValue extends ElementValue
|
||||
{
|
||||
// For annotation element values, this is the annotation
|
||||
private final AnnotationEntry annotationEntry;
|
||||
public class AnnotationElementValue extends ElementValue {
|
||||
// For annotation element values, this is the annotation
|
||||
private final AnnotationEntry annotationEntry;
|
||||
|
||||
public AnnotationElementValue(final int type, final AnnotationEntry annotationEntry,
|
||||
final ConstantPool cpool)
|
||||
{
|
||||
super(type, cpool);
|
||||
if (type != ANNOTATION) {
|
||||
throw new IllegalArgumentException(
|
||||
"Only element values of type annotation can be built with this ctor - type specified: " + type);
|
||||
}
|
||||
this.annotationEntry = annotationEntry;
|
||||
public AnnotationElementValue(final int type, final AnnotationEntry annotationEntry, final ConstantPool cpool) {
|
||||
super(type, cpool);
|
||||
if (type != ANNOTATION) {
|
||||
throw new ClassFormatException("Only element values of type annotation can be built with this ctor - type specified: " + type);
|
||||
}
|
||||
this.annotationEntry = annotationEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(final DataOutputStream dos) throws IOException
|
||||
{
|
||||
dos.writeByte(super.getType()); // u1 type of value (ANNOTATION == '@')
|
||||
annotationEntry.dump(dos);
|
||||
}
|
||||
@Override
|
||||
public void dump(final DataOutputStream dos) throws IOException {
|
||||
dos.writeByte(super.getType()); // u1 type of value (ANNOTATION == '@')
|
||||
annotationEntry.dump(dos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringifyValue()
|
||||
{
|
||||
return annotationEntry.toString();
|
||||
}
|
||||
public AnnotationEntry getAnnotationEntry() {
|
||||
return annotationEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return stringifyValue();
|
||||
}
|
||||
@Override
|
||||
public String stringifyValue() {
|
||||
return annotationEntry.toString();
|
||||
}
|
||||
|
||||
public AnnotationEntry getAnnotationEntry()
|
||||
{
|
||||
return annotationEntry;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return stringifyValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,66 +25,60 @@ import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* represents one annotation in the annotation table
|
||||
* Represents one annotation in the annotation table
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class AnnotationEntry implements Node {
|
||||
|
||||
private final int typeIndex;
|
||||
private final ConstantPool constantPool;
|
||||
private final boolean isRuntimeVisible;
|
||||
public static final AnnotationEntry[] EMPTY_ARRAY = {};
|
||||
|
||||
private List<ElementValuePair> elementValuePairs;
|
||||
public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) {
|
||||
// Find attributes that contain annotation data
|
||||
return Stream.of(attrs).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries()))
|
||||
.toArray(AnnotationEntry[]::new);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Factory method to create an AnnotionEntry from a DataInput
|
||||
*
|
||||
* @param input
|
||||
* @param constantPool
|
||||
* @param isRuntimeVisible
|
||||
* @return the entry
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public static AnnotationEntry read(final DataInput input, final ConstantPool constant_pool, final boolean isRuntimeVisible) throws IOException {
|
||||
|
||||
final AnnotationEntry annotationEntry = new AnnotationEntry(input.readUnsignedShort(), constant_pool, isRuntimeVisible);
|
||||
final int num_element_value_pairs = input.readUnsignedShort();
|
||||
public static AnnotationEntry read(final DataInput input, final ConstantPool constantPool, final boolean isRuntimeVisible) throws IOException {
|
||||
final AnnotationEntry annotationEntry = new AnnotationEntry(input.readUnsignedShort(), constantPool, isRuntimeVisible);
|
||||
final int numElementValuePairs = input.readUnsignedShort();
|
||||
annotationEntry.elementValuePairs = new ArrayList<>();
|
||||
for (int i = 0; i < num_element_value_pairs; i++) {
|
||||
annotationEntry.elementValuePairs.add(
|
||||
new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constant_pool),
|
||||
constant_pool));
|
||||
for (int i = 0; i < numElementValuePairs; i++) {
|
||||
annotationEntry.elementValuePairs
|
||||
.add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool));
|
||||
}
|
||||
return annotationEntry;
|
||||
}
|
||||
|
||||
public AnnotationEntry(final int type_index, final ConstantPool constant_pool, final boolean isRuntimeVisible) {
|
||||
this.typeIndex = type_index;
|
||||
this.constantPool = constant_pool;
|
||||
private final int typeIndex;
|
||||
|
||||
private final ConstantPool constantPool;
|
||||
|
||||
private final boolean isRuntimeVisible;
|
||||
|
||||
private List<ElementValuePair> elementValuePairs;
|
||||
|
||||
public AnnotationEntry(final int typeIndex, final ConstantPool constantPool, final boolean isRuntimeVisible) {
|
||||
this.typeIndex = typeIndex;
|
||||
this.constantPool = constantPool;
|
||||
this.isRuntimeVisible = isRuntimeVisible;
|
||||
}
|
||||
|
||||
public int getTypeIndex() {
|
||||
return typeIndex;
|
||||
}
|
||||
|
||||
public ConstantPool getConstantPool() {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
public boolean isRuntimeVisible() {
|
||||
return isRuntimeVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
@@ -94,34 +88,8 @@ public class AnnotationEntry implements Node {
|
||||
v.visitAnnotationEntry(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the annotation type name
|
||||
*/
|
||||
public String getAnnotationType() {
|
||||
final ConstantUtf8 c = (ConstantUtf8) constantPool.getConstant(typeIndex, Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the annotation type index
|
||||
*/
|
||||
public int getAnnotationTypeIndex() {
|
||||
return typeIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of element value pairs in this annotation entry
|
||||
*/
|
||||
public final int getNumElementValuePairs() {
|
||||
return elementValuePairs.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the element value pairs in this annotation entry
|
||||
*/
|
||||
public ElementValuePair[] getElementValuePairs() {
|
||||
// TODO return List
|
||||
return elementValuePairs.toArray(new ElementValuePair[elementValuePairs.size()]);
|
||||
public void addElementNameValuePair(final ElementValuePair elementNameValuePair) {
|
||||
elementValuePairs.add(elementNameValuePair);
|
||||
}
|
||||
|
||||
public void dump(final DataOutputStream dos) throws IOException {
|
||||
@@ -133,8 +101,45 @@ public class AnnotationEntry implements Node {
|
||||
}
|
||||
}
|
||||
|
||||
public void addElementNameValuePair(final ElementValuePair elementNameValuePair) {
|
||||
elementValuePairs.add(elementNameValuePair);
|
||||
/**
|
||||
* @return the annotation type name
|
||||
*/
|
||||
public String getAnnotationType() {
|
||||
return constantPool.getConstantUtf8(typeIndex).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the annotation type index
|
||||
*/
|
||||
public int getAnnotationTypeIndex() {
|
||||
return typeIndex;
|
||||
}
|
||||
|
||||
public ConstantPool getConstantPool() {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the element value pairs in this annotation entry
|
||||
*/
|
||||
public ElementValuePair[] getElementValuePairs() {
|
||||
// TODO return List
|
||||
return elementValuePairs.toArray(ElementValuePair.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of element value pairs in this annotation entry
|
||||
*/
|
||||
public final int getNumElementValuePairs() {
|
||||
return elementValuePairs.size();
|
||||
}
|
||||
|
||||
public int getTypeIndex() {
|
||||
return typeIndex;
|
||||
}
|
||||
|
||||
public boolean isRuntimeVisible() {
|
||||
return isRuntimeVisible;
|
||||
}
|
||||
|
||||
public String toShortString() {
|
||||
@@ -146,7 +151,10 @@ public class AnnotationEntry implements Node {
|
||||
result.append("(");
|
||||
for (final ElementValuePair element : evPairs) {
|
||||
result.append(element.toShortString());
|
||||
result.append(", ");
|
||||
}
|
||||
// remove last ", "
|
||||
result.setLength(result.length() - 2);
|
||||
result.append(")");
|
||||
}
|
||||
return result.toString();
|
||||
@@ -156,16 +164,4 @@ public class AnnotationEntry implements Node {
|
||||
public String toString() {
|
||||
return toShortString();
|
||||
}
|
||||
|
||||
public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) {
|
||||
// Find attributes that contain annotation data
|
||||
final List<AnnotationEntry> accumulatedAnnotations = new ArrayList<>(attrs.length);
|
||||
for (final Attribute attribute : attrs) {
|
||||
if (attribute instanceof Annotations) {
|
||||
final Annotations runtimeAnnotations = (Annotations) attribute;
|
||||
Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getAnnotationEntries());
|
||||
}
|
||||
}
|
||||
return accumulatedAnnotations.toArray(new AnnotationEntry[accumulatedAnnotations.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,40 +24,30 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* base class for annotations
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public abstract class Annotations extends Attribute {
|
||||
public abstract class Annotations extends Attribute implements Iterable<AnnotationEntry> {
|
||||
|
||||
private AnnotationEntry[] annotationTable;
|
||||
private final boolean isRuntimeVisible;
|
||||
|
||||
/**
|
||||
* @param annotation_type the subclass type of the annotation
|
||||
* @param name_index Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
*/
|
||||
Annotations(final byte annotation_type, final int name_index, final int length, final DataInput input,
|
||||
final ConstantPool constant_pool, final boolean isRuntimeVisible) throws IOException {
|
||||
this(annotation_type, name_index, length, (AnnotationEntry[]) null, constant_pool, isRuntimeVisible);
|
||||
final int annotation_table_length = input.readUnsignedShort();
|
||||
annotationTable = new AnnotationEntry[annotation_table_length];
|
||||
for (int i = 0; i < annotation_table_length; i++) {
|
||||
annotationTable[i] = AnnotationEntry.read(input, constant_pool, isRuntimeVisible);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param annotationType the subclass type of the annotation
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param annotationTable the actual annotations
|
||||
* @param constantPool Array of constants
|
||||
* Constructs an instance.
|
||||
*
|
||||
* @param annotationType the subclass type of the annotation
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param annotationTable the actual annotations
|
||||
* @param constantPool Array of constants
|
||||
* @param isRuntimeVisible whether this Annotation visible at runtime
|
||||
*/
|
||||
public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable,
|
||||
final ConstantPool constantPool, final boolean isRuntimeVisible) {
|
||||
@@ -67,8 +57,30 @@ public abstract class Annotations extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
* Constructs an instance.
|
||||
*
|
||||
* @param annotationType the subclass type of the annotation
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @param isRuntimeVisible whether this Annotation visible at runtime
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
Annotations(final byte annotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool,
|
||||
final boolean isRuntimeVisible) throws IOException {
|
||||
this(annotationType, nameIndex, length, (AnnotationEntry[]) null, constantPool, isRuntimeVisible);
|
||||
final int annotationTableLength = input.readUnsignedShort();
|
||||
annotationTable = new AnnotationEntry[annotationTableLength];
|
||||
for (int i = 0; i < annotationTableLength; i++) {
|
||||
annotationTable[i] = AnnotationEntry.read(input, constantPool, isRuntimeVisible);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@@ -77,21 +89,22 @@ public abstract class Annotations extends Attribute {
|
||||
v.visitAnnotation(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param annotationTable the entries to set in this annotation
|
||||
*/
|
||||
public final void setAnnotationTable(final AnnotationEntry[] annotationTable) {
|
||||
this.annotationTable = annotationTable;
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the array of annotation entries in this annotation
|
||||
* Gets the array of annotation entries in this annotation
|
||||
*/
|
||||
public AnnotationEntry[] getAnnotationEntries() {
|
||||
return annotationTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of annotation entries in this annotation.
|
||||
*
|
||||
* @return the number of annotation entries in this annotation
|
||||
*/
|
||||
public final int getNumAnnotations() {
|
||||
@@ -105,6 +118,38 @@ public abstract class Annotations extends Attribute {
|
||||
return isRuntimeVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<AnnotationEntry> iterator() {
|
||||
return Stream.of(annotationTable).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entries to set in this annotation.
|
||||
*
|
||||
* @param annotationTable the entries to set in this annotation
|
||||
*/
|
||||
public final void setAnnotationTable(final AnnotationEntry[] annotationTable) {
|
||||
this.annotationTable = annotationTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to a String representation.
|
||||
*
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public final String toString() {
|
||||
final StringBuilder buf = new StringBuilder(Const.getAttributeName(getTag()));
|
||||
buf.append(":\n");
|
||||
for (int i = 0; i < annotationTable.length; i++) {
|
||||
buf.append(" ").append(annotationTable[i]);
|
||||
if (i < annotationTable.length - 1) {
|
||||
buf.append('\n');
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
protected void writeAnnotations(final DataOutputStream dos) throws IOException {
|
||||
if (annotationTable == null) {
|
||||
return;
|
||||
@@ -114,4 +159,5 @@ public abstract class Annotations extends Attribute {
|
||||
element.dump(dos);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,40 +27,20 @@ import java.io.IOException;
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
public class ArrayElementValue extends ElementValue
|
||||
{
|
||||
public class ArrayElementValue extends ElementValue {
|
||||
// For array types, this is the array
|
||||
private final ElementValue[] elementValues;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("{");
|
||||
for (int i = 0; i < elementValues.length; i++)
|
||||
{
|
||||
sb.append(elementValues[i]);
|
||||
if ((i + 1) < elementValues.length) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public ArrayElementValue(final int type, final ElementValue[] datums, final ConstantPool cpool)
|
||||
{
|
||||
public ArrayElementValue(final int type, final ElementValue[] datums, final ConstantPool cpool) {
|
||||
super(type, cpool);
|
||||
if (type != ARRAY) {
|
||||
throw new IllegalArgumentException(
|
||||
"Only element values of type array can be built with this ctor - type specified: " + type);
|
||||
throw new ClassFormatException("Only element values of type array can be built with this ctor - type specified: " + type);
|
||||
}
|
||||
this.elementValues = datums;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(final DataOutputStream dos) throws IOException
|
||||
{
|
||||
public void dump(final DataOutputStream dos) throws IOException {
|
||||
dos.writeByte(super.getType()); // u1 type of value (ARRAY == '[')
|
||||
dos.writeShort(elementValues.length);
|
||||
for (final ElementValue evalue : elementValues) {
|
||||
@@ -68,15 +48,21 @@ public class ArrayElementValue extends ElementValue
|
||||
}
|
||||
}
|
||||
|
||||
public ElementValue[] getElementValuesArray() {
|
||||
return elementValues;
|
||||
}
|
||||
|
||||
public int getElementValuesArraySize() {
|
||||
return elementValues.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringifyValue()
|
||||
{
|
||||
public String stringifyValue() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
for (int i = 0; i < elementValues.length; i++)
|
||||
{
|
||||
for (int i = 0; i < elementValues.length; i++) {
|
||||
sb.append(elementValues[i].stringifyValue());
|
||||
if ((i + 1) < elementValues.length) {
|
||||
if (i + 1 < elementValues.length) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
@@ -84,13 +70,17 @@ public class ArrayElementValue extends ElementValue
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public ElementValue[] getElementValuesArray()
|
||||
{
|
||||
return elementValues;
|
||||
}
|
||||
|
||||
public int getElementValuesArraySize()
|
||||
{
|
||||
return elementValues.length;
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("{");
|
||||
for (int i = 0; i < elementValues.length; i++) {
|
||||
sb.append(elementValues[i]);
|
||||
if (i + 1 < elementValues.length) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -27,14 +27,20 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* Abstract super class for <em>Attribute</em> objects. Currently the
|
||||
* <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>,
|
||||
* <em>Exceptiontable</em>, <em>LineNumberTable</em>,
|
||||
* <em>LocalVariableTable</em>, <em>InnerClasses</em> and
|
||||
* <em>Synthetic</em> attributes are supported. The <em>Unknown</em>
|
||||
* attribute stands for non-standard-attributes.
|
||||
* Abstract super class for <em>Attribute</em> objects. Currently the <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>, <em>Exceptiontable</em>,
|
||||
* <em>LineNumberTable</em>, <em>LocalVariableTable</em>, <em>InnerClasses</em> and <em>Synthetic</em> attributes are supported. The <em>Unknown</em> attribute
|
||||
* stands for non-standard-attributes.
|
||||
*
|
||||
* <pre>
|
||||
* attribute_info {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u1 info[attribute_length];
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see ConstantValue
|
||||
* @see SourceFile
|
||||
@@ -47,28 +53,29 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
* @see Synthetic
|
||||
* @see Deprecated
|
||||
* @see Signature
|
||||
* @LastModified: May 2021
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public abstract class Attribute implements Cloneable, Node {
|
||||
private static final boolean debug = false;
|
||||
private int name_index; // Points to attribute name in constant pool
|
||||
private int length; // Content length of attribute field
|
||||
private final byte tag; // Tag to distinguish subclasses
|
||||
private ConstantPool constant_pool;
|
||||
|
||||
private static final Map<String, Object> readers = new HashMap<>();
|
||||
private static final Map<String, Object> READERS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Add an Attribute reader capable of parsing (user-defined) attributes
|
||||
* named "name". You should not add readers for the standard attributes such
|
||||
* as "LineNumberTable", because those are handled internally.
|
||||
* Empty array.
|
||||
*
|
||||
* @since 6.6.0
|
||||
*/
|
||||
public static final Attribute[] EMPTY_ARRAY = {};
|
||||
|
||||
/**
|
||||
* Add an Attribute reader capable of parsing (user-defined) attributes named "name". You should not add readers for the
|
||||
* standard attributes such as "LineNumberTable", because those are handled internally.
|
||||
*
|
||||
* @param name the name of the attribute as stored in the class file
|
||||
* @param r the reader object
|
||||
* @param unknownAttributeReader the reader object
|
||||
*/
|
||||
public static void addAttributeReader(final String name, final UnknownAttributeReader r)
|
||||
{
|
||||
readers.put(name, r);
|
||||
public static void addAttributeReader(final String name, final UnknownAttributeReader unknownAttributeReader) {
|
||||
READERS.put(name, unknownAttributeReader);
|
||||
}
|
||||
|
||||
protected static void println(final String msg) {
|
||||
@@ -78,135 +85,122 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* Class method reads one attribute from the input data stream. This method
|
||||
* must not be accessible from the outside. It is called by the Field and
|
||||
* Method constructor methods.
|
||||
* Class method reads one attribute from the input data stream. This method must not be accessible from the outside. It
|
||||
* is called by the Field and Method constructor methods.
|
||||
*
|
||||
* @see Field
|
||||
* @see Method
|
||||
*
|
||||
* @param file Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @param dataInput Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @return Attribute
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @since 6.0
|
||||
*/
|
||||
public static Attribute readAttribute(final DataInput file, final ConstantPool constant_pool)
|
||||
throws IOException, ClassFormatException
|
||||
{
|
||||
public static Attribute readAttribute(final DataInput dataInput, final ConstantPool constantPool) throws IOException {
|
||||
byte tag = Const.ATTR_UNKNOWN; // Unknown attribute
|
||||
// Get class name from constant pool via `name_index' indirection
|
||||
final int name_index = file.readUnsignedShort();
|
||||
final ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8);
|
||||
final String name = c.getBytes();
|
||||
// Get class name from constant pool via 'name_index' indirection
|
||||
final int nameIndex = dataInput.readUnsignedShort();
|
||||
final String name = constantPool.getConstantUtf8(nameIndex).getBytes();
|
||||
|
||||
// Length of data in bytes
|
||||
final int length = file.readInt();
|
||||
final int length = dataInput.readInt();
|
||||
|
||||
// Compare strings to find known attribute
|
||||
for (byte i = 0; i < Const.KNOWN_ATTRIBUTES; i++)
|
||||
{
|
||||
if (name.equals(Const.getAttributeName(i)))
|
||||
{
|
||||
for (byte i = 0; i < Const.KNOWN_ATTRIBUTES; i++) {
|
||||
if (name.equals(Const.getAttributeName(i))) {
|
||||
tag = i; // found!
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Call proper constructor, depending on `tag'
|
||||
switch (tag)
|
||||
{
|
||||
case Const.ATTR_UNKNOWN:
|
||||
final Object r = readers.get(name);
|
||||
if (r instanceof UnknownAttributeReader)
|
||||
{
|
||||
return ((UnknownAttributeReader) r).createAttribute(name_index, length, file, constant_pool);
|
||||
}
|
||||
return new Unknown(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_CONSTANT_VALUE:
|
||||
return new ConstantValue(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_SOURCE_FILE:
|
||||
return new SourceFile(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_CODE:
|
||||
return new Code(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_EXCEPTIONS:
|
||||
return new ExceptionTable(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_LINE_NUMBER_TABLE:
|
||||
return new LineNumberTable(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_LOCAL_VARIABLE_TABLE:
|
||||
return new LocalVariableTable(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_INNER_CLASSES:
|
||||
return new InnerClasses(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_SYNTHETIC:
|
||||
return new Synthetic(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_DEPRECATED:
|
||||
return new Deprecated(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_PMG:
|
||||
return new PMGClass(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_SIGNATURE:
|
||||
return new Signature(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_STACK_MAP:
|
||||
// old style stack map: unneeded for JDK5 and below;
|
||||
// illegal(?) for JDK6 and above. So just delete with a warning.
|
||||
println("Warning: Obsolete StackMap attribute ignored.");
|
||||
return new Unknown(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS:
|
||||
return new RuntimeVisibleAnnotations(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS:
|
||||
return new RuntimeInvisibleAnnotations(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS:
|
||||
return new RuntimeVisibleParameterAnnotations(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS:
|
||||
return new RuntimeInvisibleParameterAnnotations(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_ANNOTATION_DEFAULT:
|
||||
return new AnnotationDefault(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE:
|
||||
return new LocalVariableTypeTable(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_ENCLOSING_METHOD:
|
||||
return new EnclosingMethod(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_STACK_MAP_TABLE:
|
||||
// read new style stack map: StackMapTable. The rest of the code
|
||||
// calls this a StackMap for historical reasons.
|
||||
return new StackMap(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_BOOTSTRAP_METHODS:
|
||||
return new BootstrapMethods(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_METHOD_PARAMETERS:
|
||||
return new MethodParameters(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_MODULE:
|
||||
return new Module(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_MODULE_PACKAGES:
|
||||
return new ModulePackages(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_MODULE_MAIN_CLASS:
|
||||
return new ModuleMainClass(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_NEST_HOST:
|
||||
return new NestHost(name_index, length, file, constant_pool);
|
||||
case Const.ATTR_NEST_MEMBERS:
|
||||
return new NestMembers(name_index, length, file, constant_pool);
|
||||
default:
|
||||
// Never reached
|
||||
throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag);
|
||||
// Call proper constructor, depending on 'tag'
|
||||
switch (tag) {
|
||||
case Const.ATTR_UNKNOWN:
|
||||
final Object r = READERS.get(name);
|
||||
if (r instanceof UnknownAttributeReader) {
|
||||
return ((UnknownAttributeReader) r).createAttribute(nameIndex, length, dataInput, constantPool);
|
||||
}
|
||||
return new Unknown(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_CONSTANT_VALUE:
|
||||
return new ConstantValue(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_SOURCE_FILE:
|
||||
return new SourceFile(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_CODE:
|
||||
return new Code(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_EXCEPTIONS:
|
||||
return new ExceptionTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_LINE_NUMBER_TABLE:
|
||||
return new LineNumberTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_LOCAL_VARIABLE_TABLE:
|
||||
return new LocalVariableTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_INNER_CLASSES:
|
||||
return new InnerClasses(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_SYNTHETIC:
|
||||
return new Synthetic(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_DEPRECATED:
|
||||
return new Deprecated(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_PMG:
|
||||
return new PMGClass(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_SIGNATURE:
|
||||
return new Signature(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_STACK_MAP:
|
||||
// old style stack map: unneeded for JDK5 and below;
|
||||
// illegal(?) for JDK6 and above. So just delete with a warning.
|
||||
println("Warning: Obsolete StackMap attribute ignored.");
|
||||
return new Unknown(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS:
|
||||
return new RuntimeVisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS:
|
||||
return new RuntimeInvisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS:
|
||||
return new RuntimeVisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS:
|
||||
return new RuntimeInvisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_ANNOTATION_DEFAULT:
|
||||
return new AnnotationDefault(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE:
|
||||
return new LocalVariableTypeTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_ENCLOSING_METHOD:
|
||||
return new EnclosingMethod(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_STACK_MAP_TABLE:
|
||||
// read new style stack map: StackMapTable. The rest of the code
|
||||
// calls this a StackMap for historical reasons.
|
||||
return new StackMap(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_BOOTSTRAP_METHODS:
|
||||
return new BootstrapMethods(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_METHOD_PARAMETERS:
|
||||
return new MethodParameters(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_MODULE:
|
||||
return new Module(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_MODULE_PACKAGES:
|
||||
return new ModulePackages(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_MODULE_MAIN_CLASS:
|
||||
return new ModuleMainClass(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_NEST_HOST:
|
||||
return new NestHost(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_NEST_MEMBERS:
|
||||
return new NestMembers(nameIndex, length, dataInput, constantPool);
|
||||
default:
|
||||
// Never reached
|
||||
throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class method reads one attribute from the input data stream. This method
|
||||
* must not be accessible from the outside. It is called by the Field and
|
||||
* Method constructor methods.
|
||||
* Class method reads one attribute from the input data stream. This method must not be accessible from the outside. It
|
||||
* is called by the Field and Method constructor methods.
|
||||
*
|
||||
* @see Field
|
||||
* @see Method
|
||||
*
|
||||
* @param file Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @param dataInputStream Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @return Attribute
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public static Attribute readAttribute(final DataInputStream file, final ConstantPool constant_pool)
|
||||
throws IOException, ClassFormatException
|
||||
{
|
||||
return readAttribute((DataInput) file, constant_pool);
|
||||
public static Attribute readAttribute(final DataInputStream dataInputStream, final ConstantPool constantPool) throws IOException {
|
||||
return readAttribute((DataInput) dataInputStream, constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,65 +208,95 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
*
|
||||
* @param name the name of the attribute as stored in the class file
|
||||
*/
|
||||
public static void removeAttributeReader(final String name)
|
||||
{
|
||||
readers.remove(name);
|
||||
}
|
||||
|
||||
protected Attribute(final byte tag, final int name_index, final int length, final ConstantPool constant_pool)
|
||||
{
|
||||
this.tag = tag;
|
||||
this.name_index = name_index;
|
||||
this.length = length;
|
||||
this.constant_pool = constant_pool;
|
||||
public static void removeAttributeReader(final String name) {
|
||||
READERS.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int name_index; // Points to attribute name in constant pool TODO make private (has getter & setter)
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int length; // Content length of attribute field TODO make private (has getter & setter)
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected byte tag; // Tag to distinguish subclasses TODO make private & final; supposed to be immutable
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected ConstantPool constant_pool; // TODO make private (has getter & setter)
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*
|
||||
* @param v
|
||||
* Visitor object
|
||||
* <pre>
|
||||
* attribute_info {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u1 info[attribute_length];
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param tag tag.
|
||||
* @param nameIndex u2 name index.
|
||||
* @param length u4 length.
|
||||
* @param constantPool constant pool.
|
||||
*/
|
||||
protected Attribute(final byte tag, final int nameIndex, final int length, final ConstantPool constantPool) {
|
||||
this.tag = tag;
|
||||
this.name_index = Args.requireU2(nameIndex, 0, constantPool.getLength(), getClass().getSimpleName() + " name index");
|
||||
this.length = Args.requireU4(length, getClass().getSimpleName() + " attribute length");
|
||||
this.constant_pool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public abstract void accept(Visitor v);
|
||||
|
||||
/**
|
||||
* Use copy() if you want to have a deep copy(), i.e., with all references
|
||||
* copied correctly.
|
||||
* Use copy() if you want to have a deep copy(), i.e., with all references copied correctly.
|
||||
*
|
||||
* @return shallow copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Object clone()
|
||||
{
|
||||
public Object clone() {
|
||||
Attribute attr = null;
|
||||
try
|
||||
{
|
||||
try {
|
||||
attr = (Attribute) super.clone();
|
||||
}
|
||||
catch (final CloneNotSupportedException e)
|
||||
{
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
throw new Error("Clone Not Supported"); // never happens
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
* @param constantPool constant pool to save.
|
||||
* @return deep copy of this attribute.
|
||||
*/
|
||||
public abstract Attribute copy(ConstantPool _constant_pool);
|
||||
public abstract Attribute copy(ConstantPool constantPool);
|
||||
|
||||
/**
|
||||
* Dump attribute to file stream in binary format.
|
||||
* Dumps attribute to file stream in binary format.
|
||||
*
|
||||
* @param file
|
||||
* Output file stream
|
||||
* @throws IOException
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException
|
||||
{
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(name_index);
|
||||
file.writeInt(length);
|
||||
}
|
||||
@@ -281,16 +305,14 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
* @return Constant pool used by this object.
|
||||
* @see ConstantPool
|
||||
*/
|
||||
public final ConstantPool getConstantPool()
|
||||
{
|
||||
public final ConstantPool getConstantPool() {
|
||||
return constant_pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Length of attribute field in bytes.
|
||||
*/
|
||||
public final int getLength()
|
||||
{
|
||||
public final int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@@ -298,59 +320,51 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
* @return Name of attribute
|
||||
* @since 6.0
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
final ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
public String getName() {
|
||||
return constant_pool.getConstantUtf8(name_index).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name index in constant pool of attribute name.
|
||||
*/
|
||||
public final int getNameIndex()
|
||||
{
|
||||
public final int getNameIndex() {
|
||||
return name_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Tag of attribute, i.e., its type. Value may not be altered, thus there is no setTag() method.
|
||||
*/
|
||||
public final byte getTag()
|
||||
{
|
||||
public final byte getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constant_pool Constant pool to be used for this object.
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
* @see ConstantPool
|
||||
*/
|
||||
public final void setConstantPool(final ConstantPool constant_pool)
|
||||
{
|
||||
this.constant_pool = constant_pool;
|
||||
public final void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constant_pool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length length in bytes.
|
||||
*/
|
||||
public final void setLength(final int length)
|
||||
{
|
||||
public final void setLength(final int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name_index of attribute.
|
||||
* @param nameIndex of attribute.
|
||||
*/
|
||||
public final void setNameIndex(final int name_index)
|
||||
{
|
||||
this.name_index = name_index;
|
||||
public final void setNameIndex(final int nameIndex) {
|
||||
this.name_index = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return attribute name.
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
public String toString() {
|
||||
return Const.getAttributeName(tag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,9 @@
|
||||
package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
/**
|
||||
* Unknown (non-standard) attributes may be read via user-defined factory
|
||||
* objects that can be registered with the Attribute.addAttributeReader
|
||||
* method. These factory objects should implement this interface.
|
||||
|
||||
* Unknown (non-standard) attributes may be read via user-defined factory objects that can be registered with the
|
||||
* Attribute.addAttributeReader method. These factory objects should implement this interface.
|
||||
*
|
||||
* @see Attribute
|
||||
*
|
||||
* @deprecated Use UnknownAttributeReader instead
|
||||
@@ -34,30 +33,23 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
public interface AttributeReader {
|
||||
|
||||
/**
|
||||
When this attribute reader is added via the static method
|
||||
Attribute.addAttributeReader, an attribute name is associated with it.
|
||||
As the class file parser parses attributes, it will call various
|
||||
AttributeReaders based on the name of the attributes it is
|
||||
constructing.
|
||||
|
||||
@param name_index An index into the constant pool, indexing a
|
||||
ConstantUtf8 that represents the name of the attribute.
|
||||
|
||||
@param length The length of the data contained in the attribute. This
|
||||
is written into the constant pool and should agree with what the
|
||||
factory expects the length to be.
|
||||
|
||||
@param file This is the data input stream that the factory needs to read
|
||||
its data from.
|
||||
|
||||
@param constant_pool This is the constant pool associated with the
|
||||
Attribute that we are constructing.
|
||||
|
||||
@return The user-defined AttributeReader should take this data and use
|
||||
it to construct an attribute. In the case of errors, a null can be
|
||||
returned which will cause the parsing of the class file to fail.
|
||||
|
||||
@see Attribute#addAttributeReader( String, AttributeReader )
|
||||
* When this attribute reader is added via the static method Attribute.addAttributeReader, an attribute name is
|
||||
* associated with it. As the class file parser parses attributes, it will call various AttributeReaders based on the
|
||||
* name of the attributes it is constructing.
|
||||
*
|
||||
* @param nameIndex An index into the constant pool, indexing a ConstantUtf8 that represents the name of the attribute.
|
||||
*
|
||||
* @param length The length of the data contained in the attribute. This is written into the constant pool and should
|
||||
* agree with what the factory expects the length to be.
|
||||
*
|
||||
* @param file This is the data input stream that the factory needs to read its data from.
|
||||
*
|
||||
* @param constantPool This is the constant pool associated with the Attribute that we are constructing.
|
||||
*
|
||||
* @return The user-defined AttributeReader should take this data and use it to construct an attribute. In the case of
|
||||
* errors, a null can be returned which will cause the parsing of the class file to fail.
|
||||
*
|
||||
* @see Attribute#addAttributeReader( String, AttributeReader )
|
||||
*/
|
||||
Attribute createAttribute( int name_index, int length, java.io.DataInputStream file, ConstantPool constant_pool );
|
||||
Attribute createAttribute(int nameIndex, int length, java.io.DataInputStream file, ConstantPool constantPool);
|
||||
}
|
||||
|
||||
@@ -29,12 +29,11 @@ import java.util.Arrays;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents a bootstrap method attribute, i.e., the bootstrap
|
||||
* method ref, the number of bootstrap arguments and an array of the
|
||||
* bootstrap arguments.
|
||||
* This class represents a bootstrap method attribute, i.e., the bootstrap method ref, the number of bootstrap arguments
|
||||
* and an array of the bootstrap arguments.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23">
|
||||
* The class File Format : The BootstrapMethods Attribute</a>
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23"> The class File Format :
|
||||
* The BootstrapMethods Attribute</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public class BootstrapMethod implements Cloneable {
|
||||
@@ -45,9 +44,10 @@ public class BootstrapMethod implements Cloneable {
|
||||
/** Array of references to the constant_pool table */
|
||||
private int[] bootstrapArguments;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public BootstrapMethod(final BootstrapMethod c) {
|
||||
this(c.getBootstrapMethodRef(), c.getBootstrapArguments());
|
||||
@@ -57,7 +57,7 @@ public class BootstrapMethod implements Cloneable {
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param input Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
BootstrapMethod(final DataInput input) throws IOException {
|
||||
this(input.readUnsignedShort(), input.readUnsignedShort());
|
||||
@@ -68,8 +68,8 @@ public class BootstrapMethod implements Cloneable {
|
||||
}
|
||||
|
||||
// helper method
|
||||
private BootstrapMethod(final int bootstrap_method_ref, final int num_bootstrap_arguments) {
|
||||
this(bootstrap_method_ref, new int[num_bootstrap_arguments]);
|
||||
private BootstrapMethod(final int bootstrapMethodRef, final int numBootstrapArguments) {
|
||||
this(bootstrapMethodRef, new int[numBootstrapArguments]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,17 +82,29 @@ public class BootstrapMethod implements Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index into constant_pool of bootstrap_method
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
public int getBootstrapMethodRef() {
|
||||
return bootstrapMethodRef;
|
||||
public BootstrapMethod copy() {
|
||||
try {
|
||||
return (BootstrapMethod) clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
// TODO should this throw?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle
|
||||
* Dump object to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public void setBootstrapMethodRef(final int bootstrapMethodRef) {
|
||||
this.bootstrapMethodRef = bootstrapMethodRef;
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(bootstrapMethodRef);
|
||||
file.writeShort(bootstrapArguments.length);
|
||||
for (final int bootstrapArgument : bootstrapArguments) {
|
||||
file.writeShort(bootstrapArgument);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,6 +114,13 @@ public class BootstrapMethod implements Cloneable {
|
||||
return bootstrapArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index into constant_pool of bootstrap_method
|
||||
*/
|
||||
public int getBootstrapMethodRef() {
|
||||
return bootstrapMethodRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return count of number of boostrap arguments
|
||||
*/
|
||||
@@ -116,58 +135,36 @@ public class BootstrapMethod implements Cloneable {
|
||||
this.bootstrapArguments = bootstrapArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle
|
||||
*/
|
||||
public void setBootstrapMethodRef(final int bootstrapMethodRef) {
|
||||
this.bootstrapMethodRef = bootstrapMethodRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public final String toString() {
|
||||
return "BootstrapMethod(" + bootstrapMethodRef + ", " + bootstrapArguments.length + ", "
|
||||
+ Arrays.toString(bootstrapArguments) + ")";
|
||||
return "BootstrapMethod(" + bootstrapMethodRef + ", " + bootstrapArguments.length + ", " + Arrays.toString(bootstrapArguments) + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public final String toString( final ConstantPool constantPool ) {
|
||||
public final String toString(final ConstantPool constantPool) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
String bootstrap_method_name;
|
||||
bootstrap_method_name = constantPool.constantToString(bootstrapMethodRef,
|
||||
Const.CONSTANT_MethodHandle);
|
||||
buf.append(Utility.compactClassName(bootstrap_method_name, false));
|
||||
final int num_bootstrap_arguments = bootstrapArguments.length;
|
||||
if (num_bootstrap_arguments > 0) {
|
||||
final String bootstrapMethodName = constantPool.constantToString(bootstrapMethodRef, Const.CONSTANT_MethodHandle);
|
||||
buf.append(Utility.compactClassName(bootstrapMethodName, false));
|
||||
final int bootstrapArgumentsLen = bootstrapArguments.length;
|
||||
if (bootstrapArgumentsLen > 0) {
|
||||
buf.append("\nMethod Arguments:");
|
||||
for (int i = 0; i < num_bootstrap_arguments; i++) {
|
||||
for (int i = 0; i < bootstrapArgumentsLen; i++) {
|
||||
buf.append("\n ").append(i).append(": ");
|
||||
buf.append(constantPool.constantToString(constantPool.getConstant(bootstrapArguments[i])));
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump object to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
*/
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(bootstrapMethodRef);
|
||||
file.writeShort(bootstrapArguments.length);
|
||||
for (final int bootstrap_argument : bootstrapArguments) {
|
||||
file.writeShort(bootstrap_argument);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
public BootstrapMethod copy() {
|
||||
try {
|
||||
return (BootstrapMethod) clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
// TODO should this throw?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,73 +24,62 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents a BootstrapMethods attribute.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23">
|
||||
* The class File Format : The BootstrapMethods Attribute</a>
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23"> The class File Format :
|
||||
* The BootstrapMethods Attribute</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public class BootstrapMethods extends Attribute {
|
||||
public class BootstrapMethods extends Attribute implements Iterable<BootstrapMethod> {
|
||||
|
||||
private BootstrapMethod[] bootstrapMethods; // TODO this could be made final (setter is not used)
|
||||
private BootstrapMethod[] bootstrapMethods; // TODO this could be made final (setter is not used)
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public BootstrapMethods(final BootstrapMethods c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getBootstrapMethods(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param bootstrapMethods array of bootstrap methods
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public BootstrapMethods(final int name_index, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_BOOTSTRAP_METHODS, name_index, length, constant_pool);
|
||||
public BootstrapMethods(final int nameIndex, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_BOOTSTRAP_METHODS, nameIndex, length, constantPool);
|
||||
this.bootstrapMethods = bootstrapMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object from Input stream.
|
||||
*
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
BootstrapMethods(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
this(name_index, length, (BootstrapMethod[]) null, constant_pool);
|
||||
BootstrapMethods(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (BootstrapMethod[]) null, constantPool);
|
||||
|
||||
final int num_bootstrap_methods = input.readUnsignedShort();
|
||||
bootstrapMethods = new BootstrapMethod[num_bootstrap_methods];
|
||||
for (int i = 0; i < num_bootstrap_methods; i++) {
|
||||
final int numBootstrapMethods = input.readUnsignedShort();
|
||||
bootstrapMethods = new BootstrapMethod[numBootstrapMethods];
|
||||
for (int i = 0; i < numBootstrapMethods; i++) {
|
||||
bootstrapMethods[i] = new BootstrapMethod(input);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of bootstrap method "records"
|
||||
*/
|
||||
public final BootstrapMethod[] getBootstrapMethods() {
|
||||
return bootstrapMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bootstrapMethods the array of bootstrap methods
|
||||
*/
|
||||
public final void setBootstrapMethods(final BootstrapMethod[] bootstrapMethods) {
|
||||
this.bootstrapMethods = bootstrapMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@@ -103,14 +92,14 @@ public class BootstrapMethods extends Attribute {
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public BootstrapMethods copy(final ConstantPool _constant_pool) {
|
||||
public BootstrapMethods copy(final ConstantPool constantPool) {
|
||||
final BootstrapMethods c = (BootstrapMethods) clone();
|
||||
c.bootstrapMethods = new BootstrapMethod[bootstrapMethods.length];
|
||||
|
||||
for (int i = 0; i < bootstrapMethods.length; i++) {
|
||||
c.bootstrapMethods[i] = bootstrapMethods[i].copy();
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -118,18 +107,37 @@ public class BootstrapMethods extends Attribute {
|
||||
* Dump bootstrap methods attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
|
||||
file.writeShort(bootstrapMethods.length);
|
||||
for (final BootstrapMethod bootstrap_method : bootstrapMethods) {
|
||||
bootstrap_method.dump(file);
|
||||
for (final BootstrapMethod bootstrapMethod : bootstrapMethods) {
|
||||
bootstrapMethod.dump(file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of bootstrap method "records"
|
||||
*/
|
||||
public final BootstrapMethod[] getBootstrapMethods() {
|
||||
return bootstrapMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BootstrapMethod> iterator() {
|
||||
return Stream.of(bootstrapMethods).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bootstrapMethods the array of bootstrap methods
|
||||
*/
|
||||
public final void setBootstrapMethods(final BootstrapMethod[] bootstrapMethods) {
|
||||
this.bootstrapMethods = bootstrapMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@@ -143,11 +151,11 @@ public class BootstrapMethods extends Attribute {
|
||||
buf.append("\n");
|
||||
final int start = buf.length();
|
||||
buf.append(" ").append(i).append(": ");
|
||||
final int indent_count = buf.length() - start;
|
||||
final String[] lines = (bootstrapMethods[i].toString(super.getConstantPool())).split("\\r?\\n");
|
||||
final int indentCount = buf.length() - start;
|
||||
final String[] lines = bootstrapMethods[i].toString(super.getConstantPool()).split("\\r?\\n");
|
||||
buf.append(lines[0]);
|
||||
for (int j = 1; j < lines.length; j++) {
|
||||
buf.append("\n").append(" ".substring(0,indent_count)).append(lines[j]);
|
||||
buf.append("\n").append(" ", 0, indentCount).append(lines[j]);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
|
||||
@@ -24,48 +24,36 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
public class ClassElementValue extends ElementValue
|
||||
{
|
||||
public class ClassElementValue extends ElementValue {
|
||||
// For primitive types and string type, this points to the value entry in
|
||||
// the cpool
|
||||
// For 'class' this points to the class entry in the cpool
|
||||
private final int idx;
|
||||
|
||||
public ClassElementValue(final int type, final int idx, final ConstantPool cpool)
|
||||
{
|
||||
public ClassElementValue(final int type, final int idx, final ConstantPool cpool) {
|
||||
super(type, cpool);
|
||||
this.idx = idx;
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return idx;
|
||||
}
|
||||
|
||||
public String getClassString()
|
||||
{
|
||||
final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(idx,
|
||||
Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringifyValue()
|
||||
{
|
||||
final ConstantUtf8 cu8 = (ConstantUtf8) super.getConstantPool().getConstant(idx,
|
||||
Const.CONSTANT_Utf8);
|
||||
return cu8.getBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(final DataOutputStream dos) throws IOException
|
||||
{
|
||||
public void dump(final DataOutputStream dos) throws IOException {
|
||||
dos.writeByte(super.getType()); // u1 kind of value
|
||||
dos.writeShort(idx);
|
||||
}
|
||||
|
||||
public String getClassString() {
|
||||
return super.getConstantPool().getConstantUtf8(idx).getBytes();
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return idx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringifyValue() {
|
||||
return super.getConstantPool().getConstantUtf8(idx).getBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,28 +22,52 @@
|
||||
package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
/**
|
||||
* Thrown when the BCEL attempts to read a class file and determines
|
||||
* that the file is malformed or otherwise cannot be interpreted as a
|
||||
* class file.
|
||||
*
|
||||
* Thrown when the BCEL attempts to read a class file and determines that a class is malformed or otherwise cannot be interpreted as a class file.
|
||||
*/
|
||||
public class ClassFormatException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -3569097343160139969L;
|
||||
|
||||
/**
|
||||
* Constructs a new instance with {@code null} as its detail message. The cause is not initialized, and may subsequently be initialized by a call to
|
||||
* {@link #initCause}.
|
||||
*/
|
||||
public ClassFormatException() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public ClassFormatException(final String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance with the specified detail message. The cause is not initialized, and may subsequently be initialized by a call to
|
||||
* {@link #initCause}.
|
||||
*
|
||||
* @param message the detail message. The detail message is saved for later retrieval by the {@link #getMessage()} method.
|
||||
*/
|
||||
public ClassFormatException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance with the specified detail message and cause.
|
||||
* <p>
|
||||
* Note that the detail message associated with {@code cause} is <i>not</i> automatically incorporated in this runtime exception's detail message.
|
||||
*
|
||||
* @param message the detail message (which is saved for later retrieval by the {@link #getMessage()} method).
|
||||
* @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that
|
||||
* the cause is nonexistent or unknown.)
|
||||
* @since 6.0
|
||||
*/
|
||||
public ClassFormatException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance with the specified cause and a detail message of {@code (cause==null ? null : cause.toString())} (which typically contains the
|
||||
* class and detail message of {@code cause}). This constructor is useful for runtime exceptions that are little more than wrappers for other throwables.
|
||||
*
|
||||
* @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that the
|
||||
* cause is nonexistent or unknown.)
|
||||
* @since 6.7.0
|
||||
*/
|
||||
public ClassFormatException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,20 +32,17 @@ import java.util.zip.ZipFile;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* Wrapper class that parses a given Java .class file. The method <A
|
||||
* href ="#parse">parse</A> returns a <A href ="JavaClass.html">
|
||||
* JavaClass</A> object on success. When an I/O error or an
|
||||
* inconsistency occurs an appropiate exception is propagated back to
|
||||
* the caller.
|
||||
*
|
||||
* The structure and the names comply, except for a few conveniences,
|
||||
* exactly with the <A href="http://docs.oracle.com/javase/specs/">
|
||||
* JVM specification 1.0</a>. See this paper for
|
||||
* further details about the structure of a bytecode file.
|
||||
* Wrapper class that parses a given Java .class file. The method <a href ="#parse">parse</a> returns a
|
||||
* <a href ="JavaClass.html"> JavaClass</a> object on success. When an I/O error or an inconsistency occurs an
|
||||
* appropriate exception is propagated back to the caller.
|
||||
*
|
||||
* The structure and the names comply, except for a few conveniences, exactly with the
|
||||
* <a href="http://docs.oracle.com/javase/specs/"> JVM specification 1.0</a>. See this paper for further details about
|
||||
* the structure of a bytecode file.
|
||||
*/
|
||||
public final class ClassParser {
|
||||
|
||||
private static final int BUFSIZE = 8192;
|
||||
private DataInputStream dataInputStream;
|
||||
private final boolean fileOwned;
|
||||
private final String fileName;
|
||||
@@ -61,8 +58,6 @@ public final class ClassParser {
|
||||
private Method[] methods; // methods defined in the class
|
||||
private Attribute[] attributes; // attributes defined in the class
|
||||
private final boolean isZip; // Loaded from zip file
|
||||
private static final int BUFSIZE = 8192;
|
||||
|
||||
|
||||
/**
|
||||
* Parses class from the given stream.
|
||||
@@ -72,9 +67,9 @@ public final class ClassParser {
|
||||
*/
|
||||
public ClassParser(final InputStream inputStream, final String fileName) {
|
||||
this.fileName = fileName;
|
||||
fileOwned = false;
|
||||
this.fileOwned = false;
|
||||
final String clazz = inputStream.getClass().getName(); // Not a very clean solution ...
|
||||
isZip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar.");
|
||||
this.isZip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar.");
|
||||
if (inputStream instanceof DataInputStream) {
|
||||
this.dataInputStream = (DataInputStream) inputStream;
|
||||
} else {
|
||||
@@ -82,41 +77,38 @@ public final class ClassParser {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Parses class from given .class file.
|
||||
/**
|
||||
* Parses class from given .class file.
|
||||
*
|
||||
* @param fileName file name
|
||||
*/
|
||||
public ClassParser(final String fileName) {
|
||||
isZip = false;
|
||||
this.isZip = false;
|
||||
this.fileName = fileName;
|
||||
fileOwned = true;
|
||||
this.fileOwned = true;
|
||||
}
|
||||
|
||||
|
||||
/** Parses class from given .class file in a ZIP-archive
|
||||
/**
|
||||
* Parses class from given .class file in a ZIP-archive
|
||||
*
|
||||
* @param zipFile zip file name
|
||||
* @param fileName file name
|
||||
*/
|
||||
public ClassParser(final String zipFile, final String fileName) {
|
||||
isZip = true;
|
||||
fileOwned = true;
|
||||
this.isZip = true;
|
||||
this.fileOwned = true;
|
||||
this.zipFile = zipFile;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the given Java class file and return an object that represents
|
||||
* the contained data, i.e., constants, methods, fields and commands.
|
||||
* A <em>ClassFormatException</em> is raised, if the file is not a valid
|
||||
* .class file. (This does not include verification of the byte code as it
|
||||
* is performed by the java interpreter).
|
||||
* Parses the given Java class file and return an object that represents the contained data, i.e., constants, methods,
|
||||
* fields and commands. A <em>ClassFormatException</em> is raised, if the file is not a valid .class file. (This does
|
||||
* not include verification of the byte code as it is performed by the java interpreter).
|
||||
*
|
||||
* @return Class object representing the parsed class file
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
public JavaClass parse() throws IOException, ClassFormatException {
|
||||
ZipFile zip = null;
|
||||
@@ -130,11 +122,9 @@ public final class ClassParser {
|
||||
throw new IOException("File " + fileName + " not found");
|
||||
}
|
||||
|
||||
dataInputStream = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry),
|
||||
BUFSIZE));
|
||||
dataInputStream = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry), BUFSIZE));
|
||||
} else {
|
||||
dataInputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(
|
||||
fileName), BUFSIZE));
|
||||
dataInputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(fileName), BUFSIZE));
|
||||
}
|
||||
}
|
||||
/****************** Read headers ********************************/
|
||||
@@ -157,19 +147,19 @@ public final class ClassParser {
|
||||
// Read class attributes
|
||||
readAttributes();
|
||||
// Check for unknown variables
|
||||
//Unknown[] u = Unknown.getUnknownAttributes();
|
||||
//for (int i=0; i < u.length; i++)
|
||||
// System.err.println("WARNING: " + u[i]);
|
||||
// Unknown[] u = Unknown.getUnknownAttributes();
|
||||
// for (int i=0; i < u.length; i++)
|
||||
// System.err.println("WARNING: " + u[i]);
|
||||
// Everything should have been read now
|
||||
// if(file.available() > 0) {
|
||||
// int bytes = file.available();
|
||||
// byte[] buf = new byte[bytes];
|
||||
// file.read(buf);
|
||||
// if(!(isZip && (buf.length == 1))) {
|
||||
// System.err.println("WARNING: Trailing garbage at end of " + fileName);
|
||||
// System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf));
|
||||
// }
|
||||
// }
|
||||
// if(file.available() > 0) {
|
||||
// int bytes = file.available();
|
||||
// byte[] buf = new byte[bytes];
|
||||
// file.read(buf);
|
||||
// if(!(isZip && (buf.length == 1))) {
|
||||
// System.err.println("WARNING: Trailing garbage at end of " + fileName);
|
||||
// System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf));
|
||||
// }
|
||||
// }
|
||||
} finally {
|
||||
// Read everything of interest, so close the file
|
||||
if (fileOwned) {
|
||||
@@ -177,92 +167,88 @@ public final class ClassParser {
|
||||
if (dataInputStream != null) {
|
||||
dataInputStream.close();
|
||||
}
|
||||
} catch (final IOException ioe) {
|
||||
//ignore close exceptions
|
||||
} catch (final IOException ignored) {
|
||||
// ignore close exceptions
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (zip != null) {
|
||||
zip.close();
|
||||
}
|
||||
} catch (final IOException ioe) {
|
||||
//ignore close exceptions
|
||||
} catch (final IOException ignored) {
|
||||
// ignore close exceptions
|
||||
}
|
||||
}
|
||||
// Return the information we have gathered in a new object
|
||||
return new JavaClass(classNameIndex, superclassNameIndex, fileName, major, minor,
|
||||
accessFlags, constantPool, interfaces, fields, methods, attributes, isZip
|
||||
? JavaClass.ZIP
|
||||
: JavaClass.FILE);
|
||||
return new JavaClass(classNameIndex, superclassNameIndex, fileName, major, minor, accessFlags, constantPool, interfaces, fields, methods, attributes,
|
||||
isZip ? JavaClass.ZIP : JavaClass.FILE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads information about the attributes of the class.
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readAttributes() throws IOException, ClassFormatException {
|
||||
final int attributes_count = dataInputStream.readUnsignedShort();
|
||||
attributes = new Attribute[attributes_count];
|
||||
for (int i = 0; i < attributes_count; i++) {
|
||||
final int attributesCount = dataInputStream.readUnsignedShort();
|
||||
attributes = new Attribute[attributesCount];
|
||||
for (int i = 0; i < attributesCount; i++) {
|
||||
attributes[i] = Attribute.readAttribute(dataInputStream, constantPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads information about the class and its super class.
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readClassInfo() throws IOException, ClassFormatException {
|
||||
accessFlags = dataInputStream.readUnsignedShort();
|
||||
/* Interfaces are implicitely abstract, the flag should be set
|
||||
* according to the JVM specification.
|
||||
/*
|
||||
* Interfaces are implicitly abstract, the flag should be set according to the JVM specification.
|
||||
*/
|
||||
if ((accessFlags & Const.ACC_INTERFACE) != 0) {
|
||||
accessFlags |= Const.ACC_ABSTRACT;
|
||||
}
|
||||
if (((accessFlags & Const.ACC_ABSTRACT) != 0)
|
||||
&& ((accessFlags & Const.ACC_FINAL) != 0)) {
|
||||
if ((accessFlags & Const.ACC_ABSTRACT) != 0 && (accessFlags & Const.ACC_FINAL) != 0) {
|
||||
throw new ClassFormatException("Class " + fileName + " can't be both final and abstract");
|
||||
}
|
||||
classNameIndex = dataInputStream.readUnsignedShort();
|
||||
superclassNameIndex = dataInputStream.readUnsignedShort();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads constant pool entries.
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readConstantPool() throws IOException, ClassFormatException {
|
||||
constantPool = new ConstantPool(dataInputStream);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads information about the fields of the class, i.e., its variables.
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readFields() throws IOException, ClassFormatException {
|
||||
final int fields_count = dataInputStream.readUnsignedShort();
|
||||
fields = new Field[fields_count];
|
||||
for (int i = 0; i < fields_count; i++) {
|
||||
final int fieldsCount = dataInputStream.readUnsignedShort();
|
||||
fields = new Field[fieldsCount];
|
||||
for (int i = 0; i < fieldsCount; i++) {
|
||||
fields[i] = new Field(dataInputStream, constantPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************** Private utility methods **********************/
|
||||
/**
|
||||
* Checks whether the header of the file is ok.
|
||||
* Of course, this has to be the first action on successive file reads.
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
* Checks whether the header of the file is ok. Of course, this has to be the first action on successive file reads.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readID() throws IOException, ClassFormatException {
|
||||
if (dataInputStream.readInt() != Const.JVM_CLASSFILE_MAGIC) {
|
||||
@@ -270,39 +256,39 @@ public final class ClassParser {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads information about the interfaces implemented by this class.
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readInterfaces() throws IOException, ClassFormatException {
|
||||
final int interfaces_count = dataInputStream.readUnsignedShort();
|
||||
interfaces = new int[interfaces_count];
|
||||
for (int i = 0; i < interfaces_count; i++) {
|
||||
final int interfacesCount = dataInputStream.readUnsignedShort();
|
||||
interfaces = new int[interfacesCount];
|
||||
for (int i = 0; i < interfacesCount; i++) {
|
||||
interfaces[i] = dataInputStream.readUnsignedShort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads information about the methods of the class.
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readMethods() throws IOException, ClassFormatException {
|
||||
final int methods_count = dataInputStream.readUnsignedShort();
|
||||
methods = new Method[methods_count];
|
||||
for (int i = 0; i < methods_count; i++) {
|
||||
private void readMethods() throws IOException {
|
||||
final int methodsCount = dataInputStream.readUnsignedShort();
|
||||
methods = new Method[methodsCount];
|
||||
for (int i = 0; i < methodsCount; i++) {
|
||||
methods[i] = new Method(dataInputStream, constantPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads major and minor version of compiler which created the file.
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readVersion() throws IOException, ClassFormatException {
|
||||
minor = dataInputStream.readUnsignedShort();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -24,126 +23,173 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class represents a chunk of Java byte code contained in a
|
||||
* method. It is instantiated by the
|
||||
* <em>Attribute.readAttribute()</em> method. A <em>Code</em>
|
||||
* attribute contains informations about operand stack, local
|
||||
* variables, byte code and the exceptions handled within this
|
||||
* method.
|
||||
* This class represents a chunk of Java byte code contained in a method. It is instantiated by the
|
||||
* <em>Attribute.readAttribute()</em> method. A <em>Code</em> attribute contains informations about operand stack, local
|
||||
* variables, byte code and the exceptions handled within this method.
|
||||
*
|
||||
* This attribute has attributes itself, namely <em>LineNumberTable</em> which
|
||||
* is used for debugging purposes and <em>LocalVariableTable</em> which
|
||||
* contains information about the local variables.
|
||||
* This attribute has attributes itself, namely <em>LineNumberTable</em> which is used for debugging purposes and
|
||||
* <em>LocalVariableTable</em> which contains information about the local variables.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see CodeException
|
||||
* @see LineNumberTable
|
||||
* <pre>
|
||||
* Code_attribute {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u2 max_stack;
|
||||
* u2 max_locals;
|
||||
* u4 code_length;
|
||||
* u1 code[code_length];
|
||||
* u2 exception_table_length;
|
||||
* {
|
||||
* u2 start_pc;
|
||||
* u2 end_pc;
|
||||
* u2 handler_pc;
|
||||
* u2 catch_type;
|
||||
* } exception_table[exception_table_length];
|
||||
* u2 attributes_count;
|
||||
* attribute_info attributes[attributes_count];
|
||||
* }
|
||||
* </pre>
|
||||
* @see Attribute
|
||||
* @see CodeException
|
||||
* @see LineNumberTable
|
||||
* @see LocalVariableTable
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public final class Code extends Attribute {
|
||||
|
||||
private int maxStack; // Maximum size of stack used by this method // TODO this could be made final (setter is not used)
|
||||
private int maxLocals; // Number of local variables // TODO this could be made final (setter is not used)
|
||||
private int maxStack; // Maximum size of stack used by this method // TODO this could be made final (setter is not used)
|
||||
private int maxLocals; // Number of local variables // TODO this could be made final (setter is not used)
|
||||
private byte[] code; // Actual byte code
|
||||
private CodeException[] exceptionTable; // Table of handled exceptions
|
||||
private Attribute[] attributes; // or LocalVariable
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param code The source Code.
|
||||
*/
|
||||
public Code(final Code c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getMaxStack(), c.getMaxLocals(), c.getCode(), c
|
||||
.getExceptionTable(), c.getAttributes(), c.getConstantPool());
|
||||
public Code(final Code code) {
|
||||
this(code.getNameIndex(), code.getLength(), code.getMaxStack(), code.getMaxLocals(), code.getCode(), code.getExceptionTable(), code.getAttributes(),
|
||||
code.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index pointing to the name <em>Code</em>
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param file Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
Code(final int name_index, final int length, final DataInput file, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
Code(final int nameIndex, final int length, final DataInput file, final ConstantPool constantPool) throws IOException {
|
||||
// Initialize with some default values which will be overwritten later
|
||||
this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null,
|
||||
(CodeException[]) null, (Attribute[]) null, constant_pool);
|
||||
final int code_length = file.readInt();
|
||||
code = new byte[code_length]; // Read byte code
|
||||
this(nameIndex, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null, (CodeException[]) null, (Attribute[]) null, constantPool);
|
||||
final int codeLength = Args.requireU4(file.readInt(), 1, "Code length attribute");
|
||||
code = new byte[codeLength]; // Read byte code
|
||||
file.readFully(code);
|
||||
/* Read exception table that contains all regions where an exception
|
||||
* handler is active, i.e., a try { ... } catch() block.
|
||||
/*
|
||||
* Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch()
|
||||
* block.
|
||||
*/
|
||||
final int exception_table_length = file.readUnsignedShort();
|
||||
exceptionTable = new CodeException[exception_table_length];
|
||||
for (int i = 0; i < exception_table_length; i++) {
|
||||
final int exceptionTableLength = file.readUnsignedShort();
|
||||
exceptionTable = new CodeException[exceptionTableLength];
|
||||
for (int i = 0; i < exceptionTableLength; i++) {
|
||||
exceptionTable[i] = new CodeException(file);
|
||||
}
|
||||
/* Read all attributes, currently `LineNumberTable' and
|
||||
* `LocalVariableTable'
|
||||
/*
|
||||
* Read all attributes, currently 'LineNumberTable' and 'LocalVariableTable'
|
||||
*/
|
||||
final int attributes_count = file.readUnsignedShort();
|
||||
attributes = new Attribute[attributes_count];
|
||||
for (int i = 0; i < attributes_count; i++) {
|
||||
attributes[i] = Attribute.readAttribute(file, constant_pool);
|
||||
final int attributesCount = file.readUnsignedShort();
|
||||
attributes = new Attribute[attributesCount];
|
||||
for (int i = 0; i < attributesCount; i++) {
|
||||
attributes[i] = Attribute.readAttribute(file, constantPool);
|
||||
}
|
||||
/* Adjust length, because of setAttributes in this(), s.b. length
|
||||
* is incorrect, because it didn't take the internal attributes
|
||||
* into account yet! Very subtle bug, fixed in 3.1.1.
|
||||
/*
|
||||
* Adjust length, because of setAttributes in this(), s.b. length is incorrect, because it didn't take the internal
|
||||
* attributes into account yet! Very subtle bug, fixed in 3.1.1.
|
||||
*/
|
||||
super.setLength(length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index pointing to the name <em>Code</em>
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param maxStack Maximum size of stack
|
||||
* @param maxLocals Number of local variables
|
||||
* @param code Actual byte code
|
||||
* @param exceptionTable of handled exceptions
|
||||
* @param attributes Attributes of code: LineNumber or LocalVariable
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public Code(final int name_index, final int length, final int maxStack, final int maxLocals, final byte[] code,
|
||||
final CodeException[] exceptionTable, final Attribute[] attributes, final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_CODE, name_index, length, constant_pool);
|
||||
this.maxStack = maxStack;
|
||||
this.maxLocals = maxLocals;
|
||||
this.code = code != null ? code : new byte[0];
|
||||
this.exceptionTable = exceptionTable != null ? exceptionTable : new CodeException[0];
|
||||
this.attributes = attributes != null ? attributes : new Attribute[0];
|
||||
public Code(final int nameIndex, final int length, final int maxStack, final int maxLocals, final byte[] code, final CodeException[] exceptionTable,
|
||||
final Attribute[] attributes, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_CODE, nameIndex, length, constantPool);
|
||||
this.maxStack = Args.requireU2(maxStack, "maxStack");
|
||||
this.maxLocals = Args.requireU2(maxLocals, "maxLocals");
|
||||
this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY;
|
||||
this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY;
|
||||
Args.requireU2(this.exceptionTable.length, "exceptionTable.length");
|
||||
this.attributes = attributes != null ? attributes : EMPTY_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitCode(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the full size of this code attribute, minus its first 6 bytes, including the size of all its contained
|
||||
* attributes
|
||||
*/
|
||||
private int calculateLength() {
|
||||
int len = 0;
|
||||
if (attributes != null) {
|
||||
for (final Attribute attribute : attributes) {
|
||||
len += attribute.getLength() + 6 /* attribute header size */;
|
||||
}
|
||||
}
|
||||
return len + getInternalLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*
|
||||
* @param constantPool the constant pool to duplicate
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final Code c = (Code) clone();
|
||||
if (code != null) {
|
||||
c.code = code.clone();
|
||||
}
|
||||
c.setConstantPool(constantPool);
|
||||
c.exceptionTable = new CodeException[exceptionTable.length];
|
||||
Arrays.setAll(c.exceptionTable, i -> exceptionTable[i].copy());
|
||||
c.attributes = new Attribute[attributes.length];
|
||||
Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool));
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump code attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(maxStack);
|
||||
file.writeShort(maxLocals);
|
||||
@@ -159,7 +205,6 @@ public final class Code extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Collection of code attributes.
|
||||
* @see Attribute
|
||||
@@ -168,6 +213,31 @@ public final class Code extends Attribute {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Actual byte code of the method.
|
||||
*/
|
||||
public byte[] getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Table of handled exceptions.
|
||||
* @see CodeException
|
||||
*/
|
||||
public CodeException[] getExceptionTable() {
|
||||
return exceptionTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the internal length of this code attribute (minus the first 6 bytes) and excluding all its attributes
|
||||
*/
|
||||
private int getInternalLength() {
|
||||
return 2 /* maxStack */ + 2 /* maxLocals */ + 4 /* code length */
|
||||
+ code.length /* byte-code */
|
||||
+ 2 /* exception-table length */
|
||||
+ 8 * (exceptionTable == null ? 0 : exceptionTable.length) /* exception table */
|
||||
+ 2 /* attributes count */;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LineNumberTable of Code, if it has one
|
||||
@@ -181,7 +251,6 @@ public final class Code extends Attribute {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return LocalVariableTable of Code, if it has one
|
||||
*/
|
||||
@@ -194,24 +263,6 @@ public final class Code extends Attribute {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Actual byte code of the method.
|
||||
*/
|
||||
public byte[] getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Table of handled exceptions.
|
||||
* @see CodeException
|
||||
*/
|
||||
public CodeException[] getExceptionTable() {
|
||||
return exceptionTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Number of local variables.
|
||||
*/
|
||||
@@ -219,7 +270,6 @@ public final class Code extends Attribute {
|
||||
return maxLocals;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Maximum size of stack used by this method.
|
||||
*/
|
||||
@@ -227,86 +277,62 @@ public final class Code extends Attribute {
|
||||
return maxStack;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the internal length of this code attribute (minus the first 6 bytes)
|
||||
* and excluding all its attributes
|
||||
*/
|
||||
private int getInternalLength() {
|
||||
return 2 /*maxStack*/+ 2 /*maxLocals*/+ 4 /*code length*/
|
||||
+ code.length /*byte-code*/
|
||||
+ 2 /*exception-table length*/
|
||||
+ 8 * (exceptionTable == null ? 0 : exceptionTable.length) /* exception table */
|
||||
+ 2 /* attributes count */;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the full size of this code attribute, minus its first 6 bytes,
|
||||
* including the size of all its contained attributes
|
||||
*/
|
||||
private int calculateLength() {
|
||||
int len = 0;
|
||||
if (attributes != null) {
|
||||
for (final Attribute attribute : attributes) {
|
||||
len += attribute.getLength() + 6 /*attribute header size*/;
|
||||
}
|
||||
}
|
||||
return len + getInternalLength();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to set for this Code
|
||||
*/
|
||||
public void setAttributes( final Attribute[] attributes ) {
|
||||
this.attributes = attributes != null ? attributes : new Attribute[0];
|
||||
public void setAttributes(final Attribute[] attributes) {
|
||||
this.attributes = attributes != null ? attributes : EMPTY_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param code byte code
|
||||
*/
|
||||
public void setCode( final byte[] code ) {
|
||||
this.code = code != null ? code : new byte[0];
|
||||
public void setCode(final byte[] code) {
|
||||
this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param exceptionTable exception table
|
||||
*/
|
||||
public void setExceptionTable( final CodeException[] exceptionTable ) {
|
||||
this.exceptionTable = exceptionTable != null ? exceptionTable : new CodeException[0];
|
||||
public void setExceptionTable(final CodeException[] exceptionTable) {
|
||||
this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param maxLocals maximum number of local variables
|
||||
*/
|
||||
public void setMaxLocals( final int maxLocals ) {
|
||||
public void setMaxLocals(final int maxLocals) {
|
||||
this.maxLocals = maxLocals;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param maxStack maximum stack size
|
||||
*/
|
||||
public void setMaxStack( final int maxStack ) {
|
||||
public void setMaxStack(final int maxStack) {
|
||||
this.maxStack = maxStack;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation of code chunk.
|
||||
*/
|
||||
public String toString( final boolean verbose ) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this object to a String.
|
||||
*
|
||||
* @param verbose Provides verbose output when true.
|
||||
* @return String representation of code chunk.
|
||||
*/
|
||||
public String toString(final boolean verbose) {
|
||||
final StringBuilder buf = new StringBuilder(100); // CHECKSTYLE IGNORE MagicNumber
|
||||
buf.append("Code(maxStack = ").append(maxStack).append(", maxLocals = ").append(
|
||||
maxLocals).append(", code_length = ").append(code.length).append(")\n").append(
|
||||
Utility.codeToString(code, super.getConstantPool(), 0, -1, verbose));
|
||||
buf.append("Code(maxStack = ").append(maxStack).append(", maxLocals = ").append(maxLocals).append(", code_length = ").append(code.length).append(")\n")
|
||||
.append(Utility.codeToString(code, super.getConstantPool(), 0, -1, verbose));
|
||||
if (exceptionTable.length > 0) {
|
||||
buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n");
|
||||
for (final CodeException exception : exceptionTable) {
|
||||
@@ -322,38 +348,4 @@ public final class Code extends Attribute {
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation of code chunk.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*
|
||||
* @param _constant_pool the constant pool to duplicate
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final Code c = (Code) clone();
|
||||
if (code != null) {
|
||||
c.code = new byte[code.length];
|
||||
System.arraycopy(code, 0, c.code, 0, code.length);
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
c.exceptionTable = new CodeException[exceptionTable.length];
|
||||
for (int i = 0; i < exceptionTable.length; i++) {
|
||||
c.exceptionTable[i] = exceptionTable[i].copy();
|
||||
}
|
||||
c.attributes = new Attribute[attributes.length];
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
c.attributes[i] = attributes[i].copy(_constant_pool);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -25,187 +25,104 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class represents an entry in the exception table of the <em>Code</em>
|
||||
* attribute and is used only there. It contains a range in which a
|
||||
* particular exception handler is active.
|
||||
* This class represents an entry in the exception table of the <em>Code</em> attribute and is used only there. It
|
||||
* contains a range in which a particular exception handler is active.
|
||||
*
|
||||
* @see Code
|
||||
* @LastModified: May 2021
|
||||
* <pre>
|
||||
* Code_attribute {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u2 max_stack;
|
||||
* u2 max_locals;
|
||||
* u4 code_length;
|
||||
* u1 code[code_length];
|
||||
* u2 exception_table_length;
|
||||
* {
|
||||
* u2 start_pc;
|
||||
* u2 end_pc;
|
||||
* u2 handler_pc;
|
||||
* u2 catch_type;
|
||||
* } exception_table[exception_table_length];
|
||||
* u2 attributes_count;
|
||||
* attribute_info attributes[attributes_count];
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see Code
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public final class CodeException implements Cloneable, Node {
|
||||
|
||||
private int startPc; // Range in the code the exception handler is
|
||||
private int endPc; // active. startPc is inclusive, endPc exclusive
|
||||
private int handlerPc; /* Starting address of exception handler, i.e.,
|
||||
* an offset from start of code.
|
||||
*/
|
||||
private int catchType; /* If this is zero the handler catches any
|
||||
* exception, otherwise it points to the
|
||||
* exception class which is to be caught.
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
static final CodeException[] EMPTY_CODE_EXCEPTION_ARRAY = {};
|
||||
|
||||
/** Range in the code the exception handler. */
|
||||
private int startPc;
|
||||
|
||||
/** active. startPc is inclusive, endPc exclusive. */
|
||||
private int endPc;
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
* Starting address of exception handler, i.e., an offset from start of code.
|
||||
*/
|
||||
private int handlerPc;
|
||||
|
||||
/*
|
||||
* If this is zero the handler catches any exception, otherwise it points to the exception class which is to be caught.
|
||||
*/
|
||||
private int catchType;
|
||||
|
||||
/**
|
||||
* Constructs a new instance from another instance.
|
||||
*
|
||||
* @param c Source for copying.
|
||||
*/
|
||||
public CodeException(final CodeException c) {
|
||||
this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
* Constructs a new instance from a DataInput.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
CodeException(final DataInput file) throws IOException {
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
|
||||
.readUnsignedShort());
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param startPc Range in the code the exception handler is active,
|
||||
* startPc is inclusive while
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param startPc Range in the code the exception handler is active, startPc is inclusive while
|
||||
* @param endPc is exclusive
|
||||
* @param handlerPc Starting address of exception handler, i.e.,
|
||||
* an offset from start of code.
|
||||
* @param catchType If zero the handler catches any
|
||||
* exception, otherwise it points to the exception class which is
|
||||
* to be caught.
|
||||
* @param handlerPc Starting address of exception handler, i.e., an offset from start of code.
|
||||
* @param catchType If zero the handler catches any exception, otherwise it points to the exception class which is to be
|
||||
* caught.
|
||||
*/
|
||||
public CodeException(final int startPc, final int endPc, final int handlerPc, final int catchType) {
|
||||
this.startPc = startPc;
|
||||
this.endPc = endPc;
|
||||
this.handlerPc = handlerPc;
|
||||
this.catchType = catchType;
|
||||
this.startPc = Args.requireU2(startPc, "startPc");
|
||||
this.endPc = Args.requireU2(endPc, "endPc");
|
||||
this.handlerPc = Args.requireU2(handlerPc, "handlerPc");
|
||||
this.catchType = Args.requireU2(catchType, "catchType");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitCodeException(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump code exception to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
file.writeShort(startPc);
|
||||
file.writeShort(endPc);
|
||||
file.writeShort(handlerPc);
|
||||
file.writeShort(catchType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return 0, if the handler catches any exception, otherwise it points to
|
||||
* the exception class which is to be caught.
|
||||
*/
|
||||
public int getCatchType() {
|
||||
return catchType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Exclusive end index of the region where the handler is active.
|
||||
*/
|
||||
public int getEndPC() {
|
||||
return endPc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Starting address of exception handler, relative to the code.
|
||||
*/
|
||||
public int getHandlerPC() {
|
||||
return handlerPc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Inclusive start index of the region where the handler is active.
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return startPc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param catchType the type of exception that is caught
|
||||
*/
|
||||
public void setCatchType( final int catchType ) {
|
||||
this.catchType = catchType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param endPc end of handled block
|
||||
*/
|
||||
public void setEndPC( final int endPc ) {
|
||||
this.endPc = endPc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param handlerPc where the actual code is
|
||||
*/
|
||||
public void setHandlerPC( final int handlerPc ) { // TODO unused
|
||||
this.handlerPc = handlerPc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param startPc start of handled block
|
||||
*/
|
||||
public void setStartPC( final int startPc ) { // TODO unused
|
||||
this.startPc = startPc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = "
|
||||
+ handlerPc + ", catchType = " + catchType + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
public String toString( final ConstantPool cp, final boolean verbose ) {
|
||||
String str;
|
||||
if (catchType == 0) {
|
||||
str = "<Any exception>(0)";
|
||||
} else {
|
||||
str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false)
|
||||
+ (verbose ? "(" + catchType + ")" : "");
|
||||
}
|
||||
return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str;
|
||||
}
|
||||
|
||||
|
||||
public String toString( final ConstantPool cp ) {
|
||||
return toString(cp, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@@ -217,4 +134,100 @@ public final class CodeException implements Cloneable, Node {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps code exception to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(startPc);
|
||||
file.writeShort(endPc);
|
||||
file.writeShort(handlerPc);
|
||||
file.writeShort(catchType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught.
|
||||
*/
|
||||
public int getCatchType() {
|
||||
return catchType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Exclusive end index of the region where the handler is active.
|
||||
*/
|
||||
public int getEndPC() {
|
||||
return endPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Starting address of exception handler, relative to the code.
|
||||
*/
|
||||
public int getHandlerPC() {
|
||||
return handlerPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Inclusive start index of the region where the handler is active.
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return startPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param catchType the type of exception that is caught
|
||||
*/
|
||||
public void setCatchType(final int catchType) {
|
||||
this.catchType = catchType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param endPc end of handled block
|
||||
*/
|
||||
public void setEndPC(final int endPc) {
|
||||
this.endPc = endPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param handlerPc where the actual code is
|
||||
*/
|
||||
public void setHandlerPC(final int handlerPc) { // TODO unused
|
||||
this.handlerPc = handlerPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startPc start of handled block
|
||||
*/
|
||||
public void setStartPC(final int startPc) { // TODO unused
|
||||
this.startPc = startPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " + handlerPc + ", catchType = " + catchType + ")";
|
||||
}
|
||||
|
||||
public String toString(final ConstantPool cp) {
|
||||
return toString(cp, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cp constant pool source.
|
||||
* @param verbose Output more if true.
|
||||
* @return String representation.
|
||||
*/
|
||||
public String toString(final ConstantPool cp, final boolean verbose) {
|
||||
String str;
|
||||
if (catchType == 0) {
|
||||
str = "<Any exception>(0)";
|
||||
} else {
|
||||
str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) + (verbose ? "(" + catchType + ")" : "");
|
||||
}
|
||||
return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,81 +39,24 @@ public abstract class Constant implements Cloneable, Node {
|
||||
private static BCELComparator bcelComparator = new BCELComparator() {
|
||||
|
||||
@Override
|
||||
public boolean equals( final Object o1, final Object o2 ) {
|
||||
public boolean equals(final Object o1, final Object o2) {
|
||||
final Constant THIS = (Constant) o1;
|
||||
final Constant THAT = (Constant) o2;
|
||||
return Objects.equals(THIS.toString(), THAT.toString());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode( final Object o ) {
|
||||
public int hashCode(final Object o) {
|
||||
final Constant THIS = (Constant) o;
|
||||
return THIS.toString().hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
/* In fact this tag is redundant since we can distinguish different
|
||||
* `Constant' objects by their type, i.e., via `instanceof'. In some
|
||||
* places we will use the tag for switch()es anyway.
|
||||
*
|
||||
* First, we want match the specification as closely as possible. Second we
|
||||
* need the tag as an index to select the corresponding class name from the
|
||||
* `CONSTANT_NAMES' array.
|
||||
*/
|
||||
private byte tag;
|
||||
|
||||
Constant(final byte tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
* @return Comparison strategy object
|
||||
*/
|
||||
@Override
|
||||
public abstract void accept( Visitor v );
|
||||
|
||||
public abstract void dump( DataOutputStream file ) throws IOException;
|
||||
|
||||
/**
|
||||
* @return Tag of constant, i.e., its type. No setTag() method to avoid
|
||||
* confusion.
|
||||
*/
|
||||
public final byte getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return Const.getConstantName(tag) + "[" + tag + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this constant
|
||||
*/
|
||||
public Constant copy() {
|
||||
try {
|
||||
return (Constant) super.clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
// TODO should this throw?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
throw new Error("Clone Not Supported"); // never happens
|
||||
}
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,40 +110,96 @@ public abstract class Constant implements Cloneable, Node {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator( final BCELComparator comparator ) {
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns value as defined by given BCELComparator strategy.
|
||||
* By default two Constant objects are said to be equal when
|
||||
* the result of toString() is equal.
|
||||
/*
|
||||
* In fact this tag is redundant since we can distinguish different 'Constant' objects by their type, i.e., via
|
||||
* 'instanceof'. In some places we will use the tag for switch()es anyway.
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
* First, we want match the specification as closely as possible. Second we need the tag as an index to select the
|
||||
* corresponding class name from the 'CONSTANT_NAMES' array.
|
||||
*/
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected byte tag; // TODO should be private & final
|
||||
|
||||
Constant(final byte tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public boolean equals( final Object obj ) {
|
||||
public abstract void accept(Visitor v);
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
throw new Error("Clone Not Supported"); // never happens
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this constant
|
||||
*/
|
||||
public Constant copy() {
|
||||
try {
|
||||
return (Constant) super.clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
// TODO should this throw?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void dump(DataOutputStream file) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns value as defined by given BCELComparator strategy. By default two Constant objects are said to be equal when
|
||||
* the result of toString() is equal.
|
||||
*
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return bcelComparator.equals(this, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns value as defined by given BCELComparator strategy.
|
||||
* By default return the hashcode of the result of toString().
|
||||
* @return Tag of constant, i.e., its type. No setTag() method to avoid confusion.
|
||||
*/
|
||||
public final byte getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns value as defined by given BCELComparator strategy. By default return the hashcode of the result of
|
||||
* toString().
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
* @see Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return bcelComparator.hashCode(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return Const.getConstantName(tag) + "[" + tag + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* Abstract super class for Fieldref, Methodref, InterfaceMethodref and
|
||||
* InvokeDynamic constants.
|
||||
* Abstract super class for Fieldref, Methodref, InterfaceMethodref and InvokeDynamic constants.
|
||||
*
|
||||
* @see ConstantFieldref
|
||||
* @see ConstantMethodref
|
||||
@@ -42,54 +41,68 @@ public abstract class ConstantCP extends Constant {
|
||||
*/
|
||||
// Note that this field is used to store the
|
||||
// bootstrap_method_attr_index of a ConstantInvokeDynamic.
|
||||
private int class_index;
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int class_index; // TODO make private (has getter & setter)
|
||||
// This field has the same meaning for all subclasses.
|
||||
private int name_and_type_index;
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
public ConstantCP(final ConstantCP c) {
|
||||
this(c.getTag(), c.getClassIndex(), c.getNameAndTypeIndex());
|
||||
}
|
||||
|
||||
@java.lang.Deprecated
|
||||
protected int name_and_type_index; // TODO make private (has getter & setter)
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param tag Constant type tag
|
||||
* @param tag Constant type tag
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantCP(final byte tag, final DataInput file) throws IOException {
|
||||
this(tag, file.readUnsignedShort(), file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param class_index Reference to the class containing the field
|
||||
* @param name_and_type_index and the field signature
|
||||
* @param classIndex Reference to the class containing the field
|
||||
* @param nameAndTypeIndex and the field signature
|
||||
*/
|
||||
protected ConstantCP(final byte tag, final int class_index, final int name_and_type_index) {
|
||||
protected ConstantCP(final byte tag, final int classIndex, final int nameAndTypeIndex) {
|
||||
super(tag);
|
||||
this.class_index = class_index;
|
||||
this.name_and_type_index = name_and_type_index;
|
||||
this.class_index = classIndex;
|
||||
this.name_and_type_index = nameAndTypeIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantCP(final ConstantCP c) {
|
||||
this(c.getTag(), c.getClassIndex(), c.getNameAndTypeIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump constant field reference to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public final void dump( final DataOutputStream file ) throws IOException {
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeShort(class_index);
|
||||
file.writeShort(name_and_type_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Class this field belongs to.
|
||||
*/
|
||||
public String getClass(final ConstantPool cp) {
|
||||
return cp.constantToString(class_index, Const.CONSTANT_Class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Reference (index) to class this constant refers to.
|
||||
@@ -98,15 +111,6 @@ public abstract class ConstantCP extends Constant {
|
||||
return class_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param class_index points to Constant_class
|
||||
*/
|
||||
public final void setClassIndex( final int class_index ) {
|
||||
this.class_index = class_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Reference (index) to signature of the field.
|
||||
*/
|
||||
@@ -114,31 +118,27 @@ public abstract class ConstantCP extends Constant {
|
||||
return name_and_type_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_and_type_index points to Constant_NameAndType
|
||||
* @param classIndex points to Constant_class
|
||||
*/
|
||||
public final void setNameAndTypeIndex( final int name_and_type_index ) {
|
||||
this.name_and_type_index = name_and_type_index;
|
||||
public final void setClassIndex(final int classIndex) {
|
||||
this.class_index = classIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Class this field belongs to.
|
||||
* @param nameAndTypeIndex points to Constant_NameAndType
|
||||
*/
|
||||
public String getClass( final ConstantPool cp ) {
|
||||
return cp.constantToString(class_index, Const.CONSTANT_Class);
|
||||
public final void setNameAndTypeIndex(final int nameAndTypeIndex) {
|
||||
this.name_and_type_index = nameAndTypeIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*
|
||||
* not final as ConstantInvokeDynamic needs to modify
|
||||
* not final as ConstantInvokeDynamic needs to modify
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "(class_index = " + class_index + ", name_and_type_index = "
|
||||
+ name_and_type_index + ")";
|
||||
return super.toString() + "(class_index = " + class_index + ", name_and_type_index = " + name_and_type_index + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,24 +28,23 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a (external) class.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a (external) class.
|
||||
*
|
||||
* @see Constant
|
||||
* @see Constant
|
||||
*/
|
||||
public final class ConstantClass extends Constant implements ConstantObject {
|
||||
|
||||
private int nameIndex; // Identical to ConstantString except for the name
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantClass(final ConstantClass c) {
|
||||
this(c.getNameIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an instance from file data.
|
||||
*
|
||||
@@ -56,30 +55,25 @@ public final class ConstantClass extends Constant implements ConstantObject {
|
||||
this(dataInput.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex Name index in constant pool. Should refer to a
|
||||
* ConstantUtf8.
|
||||
* @param nameIndex Name index in constant pool. Should refer to a ConstantUtf8.
|
||||
*/
|
||||
public ConstantClass(final int nameIndex) {
|
||||
super(Const.CONSTANT_Class);
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantClass(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dumps constant class to file stream in binary format.
|
||||
*
|
||||
@@ -87,11 +81,25 @@ public final class ConstantClass extends Constant implements ConstantObject {
|
||||
* @throws IOException if an I/O error occurs writing to the DataOutputStream.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeShort(nameIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return dereferenced string
|
||||
*/
|
||||
public String getBytes(final ConstantPool cp) {
|
||||
return (String) getConstantValue(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue(final ConstantPool cp) {
|
||||
return cp.getConstantUtf8(nameIndex).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name index in constant pool of class name.
|
||||
@@ -100,31 +108,13 @@ public final class ConstantClass extends Constant implements ConstantObject {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex the name index in the constant pool of this Constant Class
|
||||
*/
|
||||
public void setNameIndex( final int nameIndex ) {
|
||||
public void setNameIndex(final int nameIndex) {
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/** @return String object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue( final ConstantPool cp ) {
|
||||
final Constant c = cp.getConstant(nameIndex, Const.CONSTANT_Utf8);
|
||||
return ((ConstantUtf8) c).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/** @return dereferenced string
|
||||
*/
|
||||
public String getBytes( final ConstantPool cp ) {
|
||||
return (String) getConstantValue(cp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -27,8 +27,7 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a Double object.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a Double object.
|
||||
*
|
||||
* @see Constant
|
||||
* @LastModified: Jun 2019
|
||||
@@ -37,6 +36,24 @@ public final class ConstantDouble extends Constant implements ConstantObject {
|
||||
|
||||
private double bytes;
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantDouble(final ConstantDouble c) {
|
||||
this(c.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantDouble(final DataInput file) throws IOException {
|
||||
this(file.readDouble());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes Data
|
||||
@@ -46,52 +63,29 @@ public final class ConstantDouble extends Constant implements ConstantObject {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*/
|
||||
public ConstantDouble(final ConstantDouble c) {
|
||||
this(c.getBytes());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
*/
|
||||
ConstantDouble(final DataInput file) throws IOException {
|
||||
this(file.readDouble());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantDouble(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump constant double to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeDouble(bytes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return data, i.e., 8 bytes.
|
||||
*/
|
||||
@@ -99,15 +93,21 @@ public final class ConstantDouble extends Constant implements ConstantObject {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Double object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue(final ConstantPool cp) {
|
||||
return Double.valueOf(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent the double value
|
||||
*/
|
||||
public void setBytes( final double bytes ) {
|
||||
public void setBytes(final double bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@@ -115,12 +115,4 @@ public final class ConstantDouble extends Constant implements ConstantObject {
|
||||
public String toString() {
|
||||
return super.toString() + "(bytes = " + bytes + ")";
|
||||
}
|
||||
|
||||
|
||||
/** @return Double object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue( final ConstantPool cp ) {
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,18 +27,20 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a dynamically computed constant.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a dynamically computed
|
||||
* constant.
|
||||
*
|
||||
* @see Constant
|
||||
* @see <a href="https://bugs.openjdk.java.net/secure/attachment/74618/constant-dynamic.html">
|
||||
* Change request for JEP 309</a>
|
||||
* @see Constant
|
||||
* @see <a href="https://bugs.openjdk.java.net/secure/attachment/74618/constant-dynamic.html"> Change request for JEP
|
||||
* 309</a>
|
||||
* @since 6.3
|
||||
*/
|
||||
public final class ConstantDynamic extends ConstantCP {
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantDynamic(final ConstantDynamic c) {
|
||||
this(c.getBootstrapMethodAttrIndex(), c.getNameAndTypeIndex());
|
||||
@@ -49,39 +51,37 @@ public final class ConstantDynamic extends ConstantCP {
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantDynamic(final DataInput file) throws IOException {
|
||||
this(file.readShort(), file.readShort());
|
||||
}
|
||||
|
||||
|
||||
public ConstantDynamic(final int bootstrap_method_attr_index, final int name_and_type_index) {
|
||||
super(Const.CONSTANT_Dynamic, bootstrap_method_attr_index, name_and_type_index);
|
||||
public ConstantDynamic(final int bootstrapMethodAttrIndex, final int nameAndTypeIndex) {
|
||||
super(Const.CONSTANT_Dynamic, bootstrapMethodAttrIndex, nameAndTypeIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e.,
|
||||
* the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantDynamic(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Reference (index) to bootstrap method this constant refers to.
|
||||
*
|
||||
* Note that this method is a functional duplicate of getClassIndex
|
||||
* for use by ConstantInvokeDynamic.
|
||||
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
||||
* @since 6.0
|
||||
*/
|
||||
public int getBootstrapMethodAttrIndex() {
|
||||
return super.getClassIndex(); // AKA bootstrap_method_attr_index
|
||||
return super.getClassIndex(); // AKA bootstrap_method_attr_index
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,47 +28,44 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents a constant pool reference to a field.
|
||||
*
|
||||
*/
|
||||
public final class ConstantFieldref extends ConstantCP {
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantFieldref(final ConstantFieldref c) {
|
||||
super(Const.CONSTANT_Fieldref, c.getClassIndex(), c.getNameAndTypeIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from input data.
|
||||
*
|
||||
* @param input input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantFieldref(final DataInput input) throws IOException {
|
||||
super(Const.CONSTANT_Fieldref, input);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param class_index Reference to the class containing the Field
|
||||
* @param name_and_type_index and the Field signature
|
||||
* @param classIndex Reference to the class containing the Field
|
||||
* @param nameAndTypeIndex and the Field signature
|
||||
*/
|
||||
public ConstantFieldref(final int class_index, final int name_and_type_index) {
|
||||
super(Const.CONSTANT_Fieldref, class_index, name_and_type_index);
|
||||
public ConstantFieldref(final int classIndex, final int nameAndTypeIndex) {
|
||||
super(Const.CONSTANT_Fieldref, classIndex, nameAndTypeIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of Fields,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of Fields, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantFieldref(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a float object.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a float object.
|
||||
*
|
||||
* @see Constant
|
||||
* @LastModified: Jun 2019
|
||||
@@ -37,6 +36,25 @@ public final class ConstantFloat extends Constant implements ConstantObject {
|
||||
|
||||
private float bytes;
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantFloat(final ConstantFloat c) {
|
||||
this(c.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantFloat(final DataInput file) throws IOException {
|
||||
this(file.readFloat());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes Data
|
||||
@@ -46,53 +64,29 @@ public final class ConstantFloat extends Constant implements ConstantObject {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
*/
|
||||
public ConstantFloat(final ConstantFloat c) {
|
||||
this(c.getBytes());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
*/
|
||||
ConstantFloat(final DataInput file) throws IOException {
|
||||
this(file.readFloat());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantFloat(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump constant float to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeFloat(bytes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return data, i.e., 4 bytes.
|
||||
*/
|
||||
@@ -100,15 +94,21 @@ public final class ConstantFloat extends Constant implements ConstantObject {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Float object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue(final ConstantPool cp) {
|
||||
return Float.valueOf(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent this float
|
||||
*/
|
||||
public void setBytes( final float bytes ) {
|
||||
public void setBytes(final float bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@@ -116,12 +116,4 @@ public final class ConstantFloat extends Constant implements ConstantObject {
|
||||
public String toString() {
|
||||
return super.toString() + "(bytes = " + bytes + ")";
|
||||
}
|
||||
|
||||
|
||||
/** @return Float object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue( final ConstantPool cp ) {
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to an int object.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to an int object.
|
||||
*
|
||||
* @see Constant
|
||||
* @LastModified: Jun 2019
|
||||
@@ -37,6 +36,24 @@ public final class ConstantInteger extends Constant implements ConstantObject {
|
||||
|
||||
private int bytes;
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantInteger(final ConstantInteger c) {
|
||||
this(c.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantInteger(final DataInput file) throws IOException {
|
||||
this(file.readInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes Data
|
||||
@@ -46,52 +63,29 @@ public final class ConstantInteger extends Constant implements ConstantObject {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*/
|
||||
public ConstantInteger(final ConstantInteger c) {
|
||||
this(c.getBytes());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
*/
|
||||
ConstantInteger(final DataInput file) throws IOException {
|
||||
this(file.readInt());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantInteger(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump constant integer to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeInt(bytes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return data, i.e., 4 bytes.
|
||||
*/
|
||||
@@ -99,15 +93,21 @@ public final class ConstantInteger extends Constant implements ConstantObject {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Integer object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue(final ConstantPool cp) {
|
||||
return Integer.valueOf(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent this integer
|
||||
*/
|
||||
public void setBytes( final int bytes ) {
|
||||
public void setBytes(final int bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@@ -115,12 +115,4 @@ public final class ConstantInteger extends Constant implements ConstantObject {
|
||||
public String toString() {
|
||||
return super.toString() + "(bytes = " + bytes + ")";
|
||||
}
|
||||
|
||||
|
||||
/** @return Integer object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue( final ConstantPool cp ) {
|
||||
return Integer.valueOf(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,47 +28,44 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents a constant pool reference to an interface method.
|
||||
*
|
||||
*/
|
||||
public final class ConstantInterfaceMethodref extends ConstantCP {
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantInterfaceMethodref(final ConstantInterfaceMethodref c) {
|
||||
super(Const.CONSTANT_InterfaceMethodref, c.getClassIndex(), c.getNameAndTypeIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from input data.
|
||||
*
|
||||
* @param input input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantInterfaceMethodref(final DataInput input) throws IOException {
|
||||
super(Const.CONSTANT_InterfaceMethodref, input);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param class_index Reference to the class containing the method
|
||||
* @param name_and_type_index and the method signature
|
||||
* @param classIndex Reference to the class containing the method
|
||||
* @param nameAndTypeIndex and the method signature
|
||||
*/
|
||||
public ConstantInterfaceMethodref(final int class_index, final int name_and_type_index) {
|
||||
super(Const.CONSTANT_InterfaceMethodref, class_index, name_and_type_index);
|
||||
public ConstantInterfaceMethodref(final int classIndex, final int nameAndTypeIndex) {
|
||||
super(Const.CONSTANT_InterfaceMethodref, classIndex, nameAndTypeIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantInterfaceMethodref(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,61 +27,57 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a invoke dynamic.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a invoke dynamic.
|
||||
*
|
||||
* @see Constant
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.10">
|
||||
* The CONSTANT_InvokeDynamic_info Structure in The Java Virtual Machine Specification</a>
|
||||
* @see Constant
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.10"> The
|
||||
* CONSTANT_InvokeDynamic_info Structure in The Java Virtual Machine Specification</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public final class ConstantInvokeDynamic extends ConstantCP {
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantInvokeDynamic(final ConstantInvokeDynamic c) {
|
||||
this(c.getBootstrapMethodAttrIndex(), c.getNameAndTypeIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantInvokeDynamic(final DataInput file) throws IOException {
|
||||
this(file.readShort(), file.readShort());
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
public ConstantInvokeDynamic(final int bootstrap_method_attr_index, final int name_and_type_index) {
|
||||
super(Const.CONSTANT_InvokeDynamic, bootstrap_method_attr_index, name_and_type_index);
|
||||
public ConstantInvokeDynamic(final int bootstrapMethodAttrIndex, final int nameAndTypeIndex) {
|
||||
super(Const.CONSTANT_InvokeDynamic, bootstrapMethodAttrIndex, nameAndTypeIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e.,
|
||||
* the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantInvokeDynamic(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Reference (index) to bootstrap method this constant refers to.
|
||||
*
|
||||
* Note that this method is a functional duplicate of getClassIndex
|
||||
* for use by ConstantInvokeDynamic.
|
||||
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
||||
* @since 6.0
|
||||
*/
|
||||
public int getBootstrapMethodAttrIndex() {
|
||||
return super.getClassIndex(); // AKA bootstrap_method_attr_index
|
||||
return super.getClassIndex(); // AKA bootstrap_method_attr_index
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,8 +27,7 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a long object.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a long object.
|
||||
*
|
||||
* @see Constant
|
||||
* @LastModified: Jan 2020
|
||||
@@ -37,6 +36,24 @@ public final class ConstantLong extends Constant implements ConstantObject {
|
||||
|
||||
private long bytes;
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantLong(final ConstantLong c) {
|
||||
this(c.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantLong(final DataInput file) throws IOException {
|
||||
this(file.readLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes Data
|
||||
@@ -46,52 +63,29 @@ public final class ConstantLong extends Constant implements ConstantObject {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*/
|
||||
public ConstantLong(final ConstantLong c) {
|
||||
this(c.getBytes());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
*/
|
||||
ConstantLong(final DataInput file) throws IOException {
|
||||
this(file.readLong());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantLong(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump constant long to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeLong(bytes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return data, i.e., 8 bytes.
|
||||
*/
|
||||
@@ -99,15 +93,21 @@ public final class ConstantLong extends Constant implements ConstantObject {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Long object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue(final ConstantPool cp) {
|
||||
return Long.valueOf(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent this long
|
||||
*/
|
||||
public void setBytes( final long bytes ) {
|
||||
public void setBytes(final long bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@@ -115,12 +115,4 @@ public final class ConstantLong extends Constant implements ConstantObject {
|
||||
public String toString() {
|
||||
return super.toString() + "(bytes = " + bytes + ")";
|
||||
}
|
||||
|
||||
|
||||
/** @return Long object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue( final ConstantPool cp ) {
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,9 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a method handle.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a method handle.
|
||||
*
|
||||
* @see Constant
|
||||
* @see Constant
|
||||
* @since 6.0
|
||||
*/
|
||||
public final class ConstantMethodHandle extends Constant {
|
||||
@@ -39,86 +38,76 @@ public final class ConstantMethodHandle extends Constant {
|
||||
private int referenceKind;
|
||||
private int referenceIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantMethodHandle(final ConstantMethodHandle c) {
|
||||
this(c.getReferenceKind(), c.getReferenceIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantMethodHandle(final DataInput file) throws IOException {
|
||||
this(file.readUnsignedByte(), file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
public ConstantMethodHandle(final int reference_kind, final int reference_index) {
|
||||
public ConstantMethodHandle(final int referenceKind, final int referenceIndex) {
|
||||
super(Const.CONSTANT_MethodHandle);
|
||||
this.referenceKind = reference_kind;
|
||||
this.referenceIndex = reference_index;
|
||||
this.referenceKind = referenceKind;
|
||||
this.referenceIndex = referenceIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e.,
|
||||
* the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantMethodHandle(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump method kind and index to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeByte(referenceKind);
|
||||
file.writeShort(referenceIndex);
|
||||
}
|
||||
|
||||
public int getReferenceIndex() {
|
||||
return referenceIndex;
|
||||
}
|
||||
|
||||
public int getReferenceKind() {
|
||||
return referenceKind;
|
||||
}
|
||||
|
||||
|
||||
public void setReferenceKind(final int reference_kind) {
|
||||
this.referenceKind = reference_kind;
|
||||
public void setReferenceIndex(final int referenceIndex) {
|
||||
this.referenceIndex = referenceIndex;
|
||||
}
|
||||
|
||||
|
||||
public int getReferenceIndex() {
|
||||
return referenceIndex;
|
||||
public void setReferenceKind(final int referenceKind) {
|
||||
this.referenceKind = referenceKind;
|
||||
}
|
||||
|
||||
|
||||
public void setReferenceIndex(final int reference_index) {
|
||||
this.referenceIndex = reference_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "(referenceKind = " + referenceKind +
|
||||
", referenceIndex = " + referenceIndex + ")";
|
||||
return super.toString() + "(referenceKind = " + referenceKind + ", referenceIndex = " + referenceIndex + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,78 +28,70 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a method type.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a method type.
|
||||
*
|
||||
* @see Constant
|
||||
* @see Constant
|
||||
* @since 6.0
|
||||
*/
|
||||
public final class ConstantMethodType extends Constant {
|
||||
|
||||
private int descriptorIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantMethodType(final ConstantMethodType c) {
|
||||
this(c.getDescriptorIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantMethodType(final DataInput file) throws IOException {
|
||||
this(file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
public ConstantMethodType(final int descriptor_index) {
|
||||
public ConstantMethodType(final int descriptorIndex) {
|
||||
super(Const.CONSTANT_MethodType);
|
||||
this.descriptorIndex = descriptor_index;
|
||||
this.descriptorIndex = descriptorIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e.,
|
||||
* the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantMethodType(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump name and signature index to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeShort(descriptorIndex);
|
||||
}
|
||||
|
||||
|
||||
public int getDescriptorIndex() {
|
||||
return descriptorIndex;
|
||||
}
|
||||
|
||||
|
||||
public void setDescriptorIndex(final int descriptor_index) {
|
||||
this.descriptorIndex = descriptor_index;
|
||||
public void setDescriptorIndex(final int descriptorIndex) {
|
||||
this.descriptorIndex = descriptorIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
|
||||
@@ -28,47 +28,44 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents a constant pool reference to a method.
|
||||
*
|
||||
*/
|
||||
public final class ConstantMethodref extends ConstantCP {
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantMethodref(final ConstantMethodref c) {
|
||||
super(Const.CONSTANT_Methodref, c.getClassIndex(), c.getNameAndTypeIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from input data.
|
||||
*
|
||||
* @param input input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantMethodref(final DataInput input) throws IOException {
|
||||
super(Const.CONSTANT_Methodref, input);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param class_index Reference to the class containing the method
|
||||
* @param name_and_type_index and the method signature
|
||||
* @param classIndex Reference to the class containing the method
|
||||
* @param nameAndTypeIndex and the method signature
|
||||
*/
|
||||
public ConstantMethodref(final int class_index, final int name_and_type_index) {
|
||||
super(Const.CONSTANT_Methodref, class_index, name_and_type_index);
|
||||
public ConstantMethodref(final int classIndex, final int nameAndTypeIndex) {
|
||||
super(Const.CONSTANT_Methodref, classIndex, nameAndTypeIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantMethodref(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,73 +28,83 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a module.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a module.
|
||||
*
|
||||
* <p>Note: Early access Java 9 support- currently subject to change</p>
|
||||
* <p>
|
||||
* Note: Early access Java 9 support- currently subject to change
|
||||
* </p>
|
||||
*
|
||||
* @see Constant
|
||||
* @see Constant
|
||||
* @since 6.1
|
||||
*/
|
||||
public final class ConstantModule extends Constant implements ConstantObject {
|
||||
|
||||
private int nameIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantModule(final ConstantModule c) {
|
||||
this(c.getNameIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantModule(final DataInput file) throws IOException {
|
||||
this(file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex Name index in constant pool. Should refer to a
|
||||
* ConstantUtf8.
|
||||
* @param nameIndex Name index in constant pool. Should refer to a ConstantUtf8.
|
||||
*/
|
||||
public ConstantModule(final int nameIndex) {
|
||||
super(Const.CONSTANT_Module);
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e.,
|
||||
* the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantModule(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump constant module to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeShort(nameIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return dereferenced string
|
||||
*/
|
||||
public String getBytes(final ConstantPool cp) {
|
||||
return (String) getConstantValue(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue(final ConstantPool cp) {
|
||||
return cp.getConstantUtf8(nameIndex).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name index in constant pool of module name.
|
||||
@@ -103,31 +113,13 @@ public final class ConstantModule extends Constant implements ConstantObject {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex the name index in the constant pool of this Constant Module
|
||||
*/
|
||||
public void setNameIndex( final int nameIndex ) {
|
||||
public void setNameIndex(final int nameIndex) {
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/** @return String object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue( final ConstantPool cp ) {
|
||||
final Constant c = cp.getConstant(nameIndex, Const.CONSTANT_Utf8);
|
||||
return ((ConstantUtf8) c).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/** @return dereferenced string
|
||||
*/
|
||||
public String getBytes( final ConstantPool cp ) {
|
||||
return (String) getConstantValue(cp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -28,37 +28,35 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to the name and signature
|
||||
* of a field or method.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to the name and signature of a
|
||||
* field or method.
|
||||
*
|
||||
* @see Constant
|
||||
* @see Constant
|
||||
*/
|
||||
public final class ConstantNameAndType extends Constant {
|
||||
|
||||
private int nameIndex; // Name of field/method
|
||||
private int signatureIndex; // and its signature.
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantNameAndType(final ConstantNameAndType c) {
|
||||
this(c.getNameIndex(), c.getSignatureIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantNameAndType(final DataInput file) throws IOException {
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex Name of field/method
|
||||
* @param signatureIndex and its signature
|
||||
@@ -69,33 +67,36 @@ public final class ConstantNameAndType extends Constant {
|
||||
this.signatureIndex = signatureIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantNameAndType(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump name and signature index to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeShort(nameIndex);
|
||||
file.writeShort(signatureIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return name
|
||||
*/
|
||||
public String getName(final ConstantPool cp) {
|
||||
return cp.constantToString(getNameIndex(), Const.CONSTANT_Utf8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name index in constant pool of field/method name.
|
||||
@@ -104,14 +105,13 @@ public final class ConstantNameAndType extends Constant {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/** @return name
|
||||
/**
|
||||
* @return signature
|
||||
*/
|
||||
public String getName( final ConstantPool cp ) {
|
||||
return cp.constantToString(getNameIndex(), Const.CONSTANT_Utf8);
|
||||
public String getSignature(final ConstantPool cp) {
|
||||
return cp.constantToString(getSignatureIndex(), Const.CONSTANT_Utf8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of field/method signature.
|
||||
*/
|
||||
@@ -119,36 +119,25 @@ public final class ConstantNameAndType extends Constant {
|
||||
return signatureIndex;
|
||||
}
|
||||
|
||||
|
||||
/** @return signature
|
||||
*/
|
||||
public String getSignature( final ConstantPool cp ) {
|
||||
return cp.constantToString(getSignatureIndex(), Const.CONSTANT_Utf8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex the name index of this constant
|
||||
*/
|
||||
public void setNameIndex( final int nameIndex ) {
|
||||
public void setNameIndex(final int nameIndex) {
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param signatureIndex the signature index in the constant pool of this type
|
||||
*/
|
||||
public void setSignatureIndex( final int signatureIndex ) {
|
||||
public void setSignatureIndex(final int signatureIndex) {
|
||||
this.signatureIndex = signatureIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "(nameIndex = " + nameIndex + ", signatureIndex = "
|
||||
+ signatureIndex + ")";
|
||||
return super.toString() + "(nameIndex = " + nameIndex + ", signatureIndex = " + signatureIndex + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
/**
|
||||
* This interface denotes those constants that have a "natural" value,
|
||||
* such as ConstantLong, ConstantString, etc..
|
||||
* This interface denotes those constants that have a "natural" value, such as ConstantLong, ConstantString, etc..
|
||||
*
|
||||
* @see Constant
|
||||
* @see Constant
|
||||
*/
|
||||
public interface ConstantObject {
|
||||
|
||||
/** @return object representing the constant, e.g., Long for ConstantLong
|
||||
/**
|
||||
* @return object representing the constant, e.g., Long for ConstantLong
|
||||
*/
|
||||
Object getConstantValue( ConstantPool cp );
|
||||
Object getConstantValue(ConstantPool cp);
|
||||
}
|
||||
|
||||
@@ -28,73 +28,83 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a package.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a package.
|
||||
*
|
||||
* <p>Note: Early access Java 9 support- currently subject to change</p>
|
||||
* <p>
|
||||
* Note: Early access Java 9 support- currently subject to change
|
||||
* </p>
|
||||
*
|
||||
* @see Constant
|
||||
* @see Constant
|
||||
* @since 6.1
|
||||
*/
|
||||
public final class ConstantPackage extends Constant implements ConstantObject {
|
||||
|
||||
private int nameIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantPackage(final ConstantPackage c) {
|
||||
this(c.getNameIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantPackage(final DataInput file) throws IOException {
|
||||
this(file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex Name index in constant pool. Should refer to a
|
||||
* ConstantUtf8.
|
||||
* @param nameIndex Name index in constant pool. Should refer to a ConstantUtf8.
|
||||
*/
|
||||
public ConstantPackage(final int nameIndex) {
|
||||
super(Const.CONSTANT_Package);
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e.,
|
||||
* the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantPackage(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump constant package to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeShort(nameIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return dereferenced string
|
||||
*/
|
||||
public String getBytes(final ConstantPool cp) {
|
||||
return (String) getConstantValue(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue(final ConstantPool cp) {
|
||||
return cp.getConstantUtf8(nameIndex).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name index in constant pool of package name.
|
||||
@@ -103,31 +113,13 @@ public final class ConstantPackage extends Constant implements ConstantObject {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex the name index in the constant pool of this Constant Package
|
||||
*/
|
||||
public void setNameIndex( final int nameIndex ) {
|
||||
public void setNameIndex(final int nameIndex) {
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/** @return String object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue( final ConstantPool cp ) {
|
||||
final Constant c = cp.getConstant(nameIndex, Const.CONSTANT_Utf8);
|
||||
return ((ConstantUtf8) c).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/** @return dereferenced string
|
||||
*/
|
||||
public String getBytes( final ConstantPool cp ) {
|
||||
return (String) getConstantValue(cp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -23,23 +23,49 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
|
||||
|
||||
/**
|
||||
* This class represents the constant pool, i.e., a table of constants, of
|
||||
* a parsed classfile. It may contain null references, due to the JVM
|
||||
* specification that skips an entry after an 8-byte constant (double,
|
||||
* long) entry. Those interested in generating constant pools
|
||||
* programatically should see <a href="../generic/ConstantPoolGen.html">
|
||||
* ConstantPoolGen</a>.
|
||||
|
||||
* @see Constant
|
||||
* @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen
|
||||
* @LastModified: June 2022
|
||||
* This class represents the constant pool, i.e., a table of constants, of a parsed classfile. It may contain null references, due to the JVM specification that
|
||||
* skips an entry after an 8-byte constant (double, long) entry. Those interested in generating constant pools programmatically should see
|
||||
* <a href="../generic/ConstantPoolGen.html"> ConstantPoolGen</a>.
|
||||
*
|
||||
* @see Constant
|
||||
* @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public class ConstantPool implements Cloneable, Node {
|
||||
public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
||||
|
||||
private static String escape(final String str) {
|
||||
final int len = str.length();
|
||||
final StringBuilder buf = new StringBuilder(len + 5);
|
||||
final char[] ch = str.toCharArray();
|
||||
for (int i = 0; i < len; i++) {
|
||||
switch (ch[i]) {
|
||||
case '\n':
|
||||
buf.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
buf.append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
buf.append("\\t");
|
||||
break;
|
||||
case '\b':
|
||||
buf.append("\\b");
|
||||
break;
|
||||
case '"':
|
||||
buf.append("\\\"");
|
||||
break;
|
||||
default:
|
||||
buf.append(ch[i]);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private Constant[] constantPool;
|
||||
|
||||
@@ -54,320 +80,134 @@ public class ConstantPool implements Cloneable, Node {
|
||||
* Reads constants from given input stream.
|
||||
*
|
||||
* @param input Input stream
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
* @throws IOException if problem in readUnsignedShort or readConstant
|
||||
*/
|
||||
public ConstantPool(final DataInput input) throws IOException, ClassFormatException {
|
||||
public ConstantPool(final DataInput input) throws IOException {
|
||||
byte tag;
|
||||
final int constant_pool_count = input.readUnsignedShort();
|
||||
constantPool = new Constant[constant_pool_count];
|
||||
/* constantPool[0] is unused by the compiler and may be used freely
|
||||
* by the implementation.
|
||||
final int constantPoolCount = input.readUnsignedShort();
|
||||
constantPool = new Constant[constantPoolCount];
|
||||
/*
|
||||
* constantPool[0] is unused by the compiler and may be used freely by the implementation.
|
||||
*/
|
||||
for (int i = 1; i < constant_pool_count; i++) {
|
||||
for (int i = 1; i < constantPoolCount; i++) {
|
||||
constantPool[i] = Constant.readConstant(input);
|
||||
/* Quote from the JVM specification:
|
||||
* "All eight byte constants take up two spots in the constant pool.
|
||||
* If this is the n'th byte in the constant pool, then the next item
|
||||
* will be numbered n+2"
|
||||
/*
|
||||
* Quote from the JVM specification: "All eight byte constants take up two spots in the constant pool. If this is the n'th byte in the constant
|
||||
* pool, then the next item will be numbered n+2"
|
||||
*
|
||||
* Thus we have to increment the index counter.
|
||||
*/
|
||||
tag = constantPool[i].getTag();
|
||||
if ((tag == Const.CONSTANT_Double) || (tag == Const.CONSTANT_Long)) {
|
||||
if (tag == Const.CONSTANT_Double || tag == Const.CONSTANT_Long) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e., the hierarchy of methods, fields,
|
||||
* attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantPool(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves constant to a string representation.
|
||||
*
|
||||
* @param c Constant to be printed
|
||||
* @param c Constant to be printed
|
||||
* @return String representation
|
||||
* @throws IllegalArgumentException if c is unknown constant type
|
||||
*/
|
||||
public String constantToString( Constant c ) throws ClassFormatException {
|
||||
public String constantToString(Constant c) throws IllegalArgumentException {
|
||||
String str;
|
||||
int i;
|
||||
final byte tag = c.getTag();
|
||||
switch (tag) {
|
||||
case Const.CONSTANT_Class:
|
||||
i = ((ConstantClass) c).getNameIndex();
|
||||
c = getConstant(i, Const.CONSTANT_Utf8);
|
||||
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
||||
break;
|
||||
case Const.CONSTANT_String:
|
||||
i = ((ConstantString) c).getStringIndex();
|
||||
c = getConstant(i, Const.CONSTANT_Utf8);
|
||||
str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\"";
|
||||
break;
|
||||
case Const.CONSTANT_Utf8:
|
||||
str = ((ConstantUtf8) c).getBytes();
|
||||
break;
|
||||
case Const.CONSTANT_Double:
|
||||
str = String.valueOf(((ConstantDouble) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Float:
|
||||
str = String.valueOf(((ConstantFloat) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Long:
|
||||
str = String.valueOf(((ConstantLong) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Integer:
|
||||
str = String.valueOf(((ConstantInteger) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_NameAndType:
|
||||
str = constantToString(((ConstantNameAndType) c).getNameIndex(),
|
||||
Const.CONSTANT_Utf8)
|
||||
+ " " + constantToString(((ConstantNameAndType) c).getSignatureIndex(),
|
||||
Const.CONSTANT_Utf8);
|
||||
break;
|
||||
case Const.CONSTANT_InterfaceMethodref:
|
||||
case Const.CONSTANT_Methodref:
|
||||
case Const.CONSTANT_Fieldref:
|
||||
str = constantToString(((ConstantCP) c).getClassIndex(), Const.CONSTANT_Class)
|
||||
+ "." + constantToString(((ConstantCP) c).getNameAndTypeIndex(),
|
||||
Const.CONSTANT_NameAndType);
|
||||
break;
|
||||
case Const.CONSTANT_MethodHandle:
|
||||
// Note that the ReferenceIndex may point to a Fieldref, Methodref or
|
||||
// InterfaceMethodref - so we need to peek ahead to get the actual type.
|
||||
final ConstantMethodHandle cmh = (ConstantMethodHandle) c;
|
||||
str = Const.getMethodHandleName(cmh.getReferenceKind())
|
||||
+ " " + constantToString(cmh.getReferenceIndex(),
|
||||
getConstant(cmh.getReferenceIndex()).getTag());
|
||||
break;
|
||||
case Const.CONSTANT_MethodType:
|
||||
final ConstantMethodType cmt = (ConstantMethodType) c;
|
||||
str = constantToString(cmt.getDescriptorIndex(), Const.CONSTANT_Utf8);
|
||||
break;
|
||||
case Const.CONSTANT_InvokeDynamic:
|
||||
final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) c;
|
||||
str = cid.getBootstrapMethodAttrIndex()
|
||||
+ ":" + constantToString(cid.getNameAndTypeIndex(),
|
||||
Const.CONSTANT_NameAndType);
|
||||
break;
|
||||
case Const.CONSTANT_Module:
|
||||
i = ((ConstantModule) c).getNameIndex();
|
||||
c = getConstant(i, Const.CONSTANT_Utf8);
|
||||
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
||||
break;
|
||||
case Const.CONSTANT_Package:
|
||||
i = ((ConstantPackage) c).getNameIndex();
|
||||
c = getConstant(i, Const.CONSTANT_Utf8);
|
||||
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
||||
break;
|
||||
default: // Never reached
|
||||
throw new IllegalArgumentException("Unknown constant type " + tag);
|
||||
case Const.CONSTANT_Class:
|
||||
i = ((ConstantClass) c).getNameIndex();
|
||||
c = getConstantUtf8(i);
|
||||
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
||||
break;
|
||||
case Const.CONSTANT_String:
|
||||
i = ((ConstantString) c).getStringIndex();
|
||||
c = getConstantUtf8(i);
|
||||
str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\"";
|
||||
break;
|
||||
case Const.CONSTANT_Utf8:
|
||||
str = ((ConstantUtf8) c).getBytes();
|
||||
break;
|
||||
case Const.CONSTANT_Double:
|
||||
str = String.valueOf(((ConstantDouble) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Float:
|
||||
str = String.valueOf(((ConstantFloat) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Long:
|
||||
str = String.valueOf(((ConstantLong) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Integer:
|
||||
str = String.valueOf(((ConstantInteger) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_NameAndType:
|
||||
str = constantToString(((ConstantNameAndType) c).getNameIndex(), Const.CONSTANT_Utf8) + " "
|
||||
+ constantToString(((ConstantNameAndType) c).getSignatureIndex(), Const.CONSTANT_Utf8);
|
||||
break;
|
||||
case Const.CONSTANT_InterfaceMethodref:
|
||||
case Const.CONSTANT_Methodref:
|
||||
case Const.CONSTANT_Fieldref:
|
||||
str = constantToString(((ConstantCP) c).getClassIndex(), Const.CONSTANT_Class) + "."
|
||||
+ constantToString(((ConstantCP) c).getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
|
||||
break;
|
||||
case Const.CONSTANT_MethodHandle:
|
||||
// Note that the ReferenceIndex may point to a Fieldref, Methodref or
|
||||
// InterfaceMethodref - so we need to peek ahead to get the actual type.
|
||||
final ConstantMethodHandle cmh = (ConstantMethodHandle) c;
|
||||
str = Const.getMethodHandleName(cmh.getReferenceKind()) + " "
|
||||
+ constantToString(cmh.getReferenceIndex(), getConstant(cmh.getReferenceIndex()).getTag());
|
||||
break;
|
||||
case Const.CONSTANT_MethodType:
|
||||
final ConstantMethodType cmt = (ConstantMethodType) c;
|
||||
str = constantToString(cmt.getDescriptorIndex(), Const.CONSTANT_Utf8);
|
||||
break;
|
||||
case Const.CONSTANT_InvokeDynamic:
|
||||
final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) c;
|
||||
str = cid.getBootstrapMethodAttrIndex() + ":" + constantToString(cid.getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
|
||||
break;
|
||||
case Const.CONSTANT_Dynamic:
|
||||
final ConstantDynamic cd = (ConstantDynamic) c;
|
||||
str = cd.getBootstrapMethodAttrIndex() + ":" + constantToString(cd.getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
|
||||
break;
|
||||
case Const.CONSTANT_Module:
|
||||
i = ((ConstantModule) c).getNameIndex();
|
||||
c = getConstantUtf8(i);
|
||||
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
||||
break;
|
||||
case Const.CONSTANT_Package:
|
||||
i = ((ConstantPackage) c).getNameIndex();
|
||||
c = getConstantUtf8(i);
|
||||
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
||||
break;
|
||||
default: // Never reached
|
||||
throw new IllegalArgumentException("Unknown constant type " + tag);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private static String escape( final String str ) {
|
||||
final int len = str.length();
|
||||
final StringBuilder buf = new StringBuilder(len + 5);
|
||||
final char[] ch = str.toCharArray();
|
||||
for (int i = 0; i < len; i++) {
|
||||
switch (ch[i]) {
|
||||
case '\n':
|
||||
buf.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
buf.append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
buf.append("\\t");
|
||||
break;
|
||||
case '\b':
|
||||
buf.append("\\b");
|
||||
break;
|
||||
case '"':
|
||||
buf.append("\\\"");
|
||||
break;
|
||||
default:
|
||||
buf.append(ch[i]);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves constant at `index' from constant pool and resolve it to
|
||||
* a string representation.
|
||||
* Retrieves constant at 'index' from constant pool and resolve it to a string representation.
|
||||
*
|
||||
* @param index of constant in constant pool
|
||||
* @param tag expected type
|
||||
* @param index of constant in constant pool
|
||||
* @param tag expected type
|
||||
* @return String representation
|
||||
*/
|
||||
public String constantToString( final int index, final byte tag ) throws ClassFormatException {
|
||||
final Constant c = getConstant(index, tag);
|
||||
return constantToString(c);
|
||||
public String constantToString(final int index, final byte tag) {
|
||||
return constantToString(getConstant(index, tag));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump constant pool to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
/*
|
||||
* Constants over the size of the constant pool shall not be written out.
|
||||
* This is a redundant measure as the ConstantPoolGen should have already
|
||||
* reported an error back in the situation.
|
||||
*/
|
||||
int size = constantPool.length < ConstantPoolGen.CONSTANT_POOL_SIZE ?
|
||||
constantPool.length : ConstantPoolGen.CONSTANT_POOL_SIZE;
|
||||
|
||||
file.writeShort(size);
|
||||
for (int i = 1; i < size; i++) {
|
||||
if (constantPool[i] != null) {
|
||||
constantPool[i].dump(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant from constant pool.
|
||||
*
|
||||
* @param index Index in constant pool
|
||||
* @return Constant value
|
||||
* @see Constant
|
||||
*/
|
||||
public Constant getConstant( final int index ) {
|
||||
if (index >= constantPool.length || index < 0) {
|
||||
throw new ClassFormatException("Invalid constant pool reference: " + index
|
||||
+ ". Constant pool size is: " + constantPool.length);
|
||||
}
|
||||
return constantPool[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant from constant pool and check whether it has the
|
||||
* expected type.
|
||||
*
|
||||
* @param index Index in constant pool
|
||||
* @param tag Tag of expected constant, i.e., its type
|
||||
* @return Constant value
|
||||
* @see Constant
|
||||
* @throws ClassFormatException
|
||||
*/
|
||||
public Constant getConstant( final int index, final byte tag ) throws ClassFormatException {
|
||||
Constant c;
|
||||
c = getConstant(index);
|
||||
if (c == null) {
|
||||
throw new ClassFormatException("Constant pool at index " + index + " is null.");
|
||||
}
|
||||
if (c.getTag() != tag) {
|
||||
throw new ClassFormatException("Expected class `" + Const.getConstantName(tag)
|
||||
+ "' at index " + index + " and got " + c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Array of constants.
|
||||
* @see Constant
|
||||
*/
|
||||
public Constant[] getConstantPool() {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets string from constant pool and bypass the indirection of
|
||||
* `ConstantClass' and `ConstantString' objects. I.e. these classes have
|
||||
* an index field that points to another entry of the constant pool of
|
||||
* type `ConstantUtf8' which contains the real data.
|
||||
*
|
||||
* @param index Index in constant pool
|
||||
* @param tag Tag of expected constant, either ConstantClass or ConstantString
|
||||
* @return Contents of string reference
|
||||
* @see ConstantClass
|
||||
* @see ConstantString
|
||||
* @throws ClassFormatException
|
||||
*/
|
||||
public String getConstantString( final int index, final byte tag ) throws ClassFormatException {
|
||||
Constant c;
|
||||
int i;
|
||||
c = getConstant(index, tag);
|
||||
/* This switch() is not that elegant, since the four classes have the
|
||||
* same contents, they just differ in the name of the index
|
||||
* field variable.
|
||||
* But we want to stick to the JVM naming conventions closely though
|
||||
* we could have solved these more elegantly by using the same
|
||||
* variable name or by subclassing.
|
||||
*/
|
||||
switch (tag) {
|
||||
case Const.CONSTANT_Class:
|
||||
i = ((ConstantClass) c).getNameIndex();
|
||||
break;
|
||||
case Const.CONSTANT_String:
|
||||
i = ((ConstantString) c).getStringIndex();
|
||||
break;
|
||||
case Const.CONSTANT_Module:
|
||||
i = ((ConstantModule) c).getNameIndex();
|
||||
break;
|
||||
case Const.CONSTANT_Package:
|
||||
i = ((ConstantPackage) c).getNameIndex();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("getConstantString called with illegal tag " + tag);
|
||||
}
|
||||
// Finally get the string from the constant pool
|
||||
c = getConstant(i, Const.CONSTANT_Utf8);
|
||||
return ((ConstantUtf8) c).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Length of constant pool.
|
||||
*/
|
||||
public int getLength() {
|
||||
return constantPool == null ? 0 : constantPool.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param constant Constant to set
|
||||
*/
|
||||
public void setConstant( final int index, final Constant constant ) {
|
||||
constantPool[index] = constant;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param constantPool
|
||||
*/
|
||||
public void setConstantPool( final Constant[] constantPool ) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
for (int i = 1; i < constantPool.length; i++) {
|
||||
buf.append(i).append(")").append(constantPool[i]).append("\n");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this constant pool
|
||||
*/
|
||||
@@ -386,4 +226,213 @@ public class ConstantPool implements Cloneable, Node {
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump constant pool to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if problem in writeShort or dump
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
/*
|
||||
* Constants over the size of the constant pool shall not be written out.
|
||||
* This is a redundant measure as the ConstantPoolGen should have already
|
||||
* reported an error back in the situation.
|
||||
*/
|
||||
final int size = Math.min(constantPool.length, Const.MAX_CP_ENTRIES);
|
||||
|
||||
file.writeShort(size);
|
||||
for (int i = 1; i < size; i++) {
|
||||
if (constantPool[i] != null) {
|
||||
constantPool[i].dump(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant from constant pool.
|
||||
*
|
||||
* @param index Index in constant pool
|
||||
* @return Constant value
|
||||
* @see Constant
|
||||
* @throws ClassFormatException if index is invalid
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Constant> T getConstant(final int index) throws ClassFormatException {
|
||||
return (T) getConstant(index, Constant.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant from constant pool and check whether it has the expected type.
|
||||
*
|
||||
* @param index Index in constant pool
|
||||
* @param tag Tag of expected constant, i.e., its type
|
||||
* @return Constant value
|
||||
* @see Constant
|
||||
* @throws ClassFormatException if constant type does not match tag
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Constant> T getConstant(final int index, final byte tag) throws ClassFormatException {
|
||||
return (T) getConstant(index, tag, Constant.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant from constant pool and check whether it has the expected type.
|
||||
*
|
||||
* @param index Index in constant pool
|
||||
* @param tag Tag of expected constant, i.e., its type
|
||||
* @return Constant value
|
||||
* @see Constant
|
||||
* @throws ClassFormatException if constant type does not match tag
|
||||
* @since 6.6.0
|
||||
*/
|
||||
public <T extends Constant> T getConstant(final int index, final byte tag, final Class<T> castTo) throws ClassFormatException {
|
||||
final T c = getConstant(index);
|
||||
if (c.getTag() != tag) {
|
||||
throw new ClassFormatException("Expected class '" + Const.getConstantName(tag) + "' at index " + index + " and got " + c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant from constant pool.
|
||||
*
|
||||
* @param <T> A {@link Constant} subclass
|
||||
* @param index Index in constant pool
|
||||
* @param castTo The {@link Constant} subclass to cast to.
|
||||
* @return Constant value
|
||||
* @see Constant
|
||||
* @throws ClassFormatException if index is invalid
|
||||
* @since 6.6.0
|
||||
*/
|
||||
public <T extends Constant> T getConstant(final int index, final Class<T> castTo) throws ClassFormatException {
|
||||
if (index >= constantPool.length || index < 0) {
|
||||
throw new ClassFormatException("Invalid constant pool reference using index: " + index + ". Constant pool size is: " + constantPool.length);
|
||||
}
|
||||
if (constantPool[index] != null && !castTo.isAssignableFrom(constantPool[index].getClass())) {
|
||||
throw new ClassFormatException("Invalid constant pool reference at index: " + index +
|
||||
". Expected " + castTo + " but was " + constantPool[index].getClass());
|
||||
}
|
||||
// Previous check ensures this won't throw a ClassCastException
|
||||
final T c = castTo.cast(constantPool[index]);
|
||||
if (c == null
|
||||
// the 0th element is always null
|
||||
&& index != 0) {
|
||||
final Constant prev = constantPool[index - 1];
|
||||
if (prev == null || prev.getTag() != Const.CONSTANT_Double && prev.getTag() != Const.CONSTANT_Long) {
|
||||
throw new ClassFormatException("Constant pool at index " + index + " is null.");
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant from constant pool and check whether it has the expected type.
|
||||
*
|
||||
* @param index Index in constant pool
|
||||
* @return ConstantInteger value
|
||||
* @see ConstantInteger
|
||||
* @throws ClassFormatException if constant type does not match tag
|
||||
*/
|
||||
public ConstantInteger getConstantInteger(final int index) {
|
||||
return getConstant(index, Const.CONSTANT_Integer, ConstantInteger.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Array of constants.
|
||||
* @see Constant
|
||||
*/
|
||||
public Constant[] getConstantPool() {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets string from constant pool and bypass the indirection of 'ConstantClass' and 'ConstantString' objects. I.e. these classes have an index field that
|
||||
* points to another entry of the constant pool of type 'ConstantUtf8' which contains the real data.
|
||||
*
|
||||
* @param index Index in constant pool
|
||||
* @param tag Tag of expected constant, either ConstantClass or ConstantString
|
||||
* @return Contents of string reference
|
||||
* @see ConstantClass
|
||||
* @see ConstantString
|
||||
* @throws IllegalArgumentException if tag is invalid
|
||||
*/
|
||||
public String getConstantString(final int index, final byte tag) throws IllegalArgumentException {
|
||||
int i;
|
||||
/*
|
||||
* This switch() is not that elegant, since the four classes have the same contents, they just differ in the name of the index field variable. But we
|
||||
* want to stick to the JVM naming conventions closely though we could have solved these more elegantly by using the same variable name or by
|
||||
* subclassing.
|
||||
*/
|
||||
switch (tag) {
|
||||
case Const.CONSTANT_Class:
|
||||
i = getConstant(index, ConstantClass.class).getNameIndex();
|
||||
break;
|
||||
case Const.CONSTANT_String:
|
||||
i = getConstant(index, ConstantString.class).getStringIndex();
|
||||
break;
|
||||
case Const.CONSTANT_Module:
|
||||
i = getConstant(index, ConstantModule.class).getNameIndex();
|
||||
break;
|
||||
case Const.CONSTANT_Package:
|
||||
i = getConstant(index, ConstantPackage.class).getNameIndex();
|
||||
break;
|
||||
case Const.CONSTANT_Utf8:
|
||||
return getConstantUtf8(index).getBytes();
|
||||
default:
|
||||
throw new IllegalArgumentException("getConstantString called with illegal tag " + tag);
|
||||
}
|
||||
// Finally get the string from the constant pool
|
||||
return getConstantUtf8(i).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant from constant pool and check whether it has the expected type.
|
||||
*
|
||||
* @param index Index in constant pool
|
||||
* @return ConstantUtf8 value
|
||||
* @see ConstantUtf8
|
||||
* @throws ClassFormatException if constant type does not match tag
|
||||
*/
|
||||
public ConstantUtf8 getConstantUtf8(final int index) throws ClassFormatException {
|
||||
return getConstant(index, Const.CONSTANT_Utf8, ConstantUtf8.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Length of constant pool.
|
||||
*/
|
||||
public int getLength() {
|
||||
return constantPool == null ? 0 : constantPool.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Constant> iterator() {
|
||||
return Arrays.stream(constantPool).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constant Constant to set
|
||||
*/
|
||||
public void setConstant(final int index, final Constant constant) {
|
||||
constantPool[index] = constant;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool
|
||||
*/
|
||||
public void setConstantPool(final Constant[] constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
for (int i = 1; i < constantPool.length; i++) {
|
||||
buf.append(i).append(")").append(constantPool[i]).append("\n");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,35 +28,33 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from the abstract {@link Constant}
|
||||
* and represents a reference to a String object.
|
||||
* This class is derived from the abstract {@link Constant} and represents a reference to a String object.
|
||||
*
|
||||
* @see Constant
|
||||
* @see Constant
|
||||
*/
|
||||
public final class ConstantString extends Constant implements ConstantObject {
|
||||
|
||||
private int stringIndex; // Identical to ConstantClass except for this name
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantString(final ConstantString c) {
|
||||
this(c.getStringIndex());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantString(final DataInput file) throws IOException {
|
||||
this(file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param stringIndex Index of Constant_Utf8 in constant pool
|
||||
*/
|
||||
@@ -65,32 +63,43 @@ public final class ConstantString extends Constant implements ConstantObject {
|
||||
this.stringIndex = stringIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantString(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump constant field reference to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(super.getTag());
|
||||
file.writeShort(stringIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return dereferenced string
|
||||
*/
|
||||
public String getBytes(final ConstantPool cp) {
|
||||
return (String) getConstantValue(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue(final ConstantPool cp) {
|
||||
return cp.getConstantUtf8(stringIndex).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of the string (ConstantUtf8).
|
||||
@@ -99,15 +108,13 @@ public final class ConstantString extends Constant implements ConstantObject {
|
||||
return stringIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param stringIndex the index into the constant of the string value
|
||||
*/
|
||||
public void setStringIndex( final int stringIndex ) {
|
||||
public void setStringIndex(final int stringIndex) {
|
||||
this.stringIndex = stringIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@@ -115,20 +122,4 @@ public final class ConstantString extends Constant implements ConstantObject {
|
||||
public String toString() {
|
||||
return super.toString() + "(stringIndex = " + stringIndex + ")";
|
||||
}
|
||||
|
||||
|
||||
/** @return String object
|
||||
*/
|
||||
@Override
|
||||
public Object getConstantValue( final ConstantPool cp ) {
|
||||
final Constant c = cp.getConstant(stringIndex, Const.CONSTANT_Utf8);
|
||||
return ((ConstantUtf8) c).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/** @return dereferenced string
|
||||
*/
|
||||
public String getBytes( final ConstantPool cp ) {
|
||||
return (String) getConstantValue(cp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -20,19 +20,45 @@
|
||||
|
||||
package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* Extends the abstract {@link Constant} to represent a reference to a UTF-8 encoded string.
|
||||
* <p>
|
||||
* The following system properties govern caching this class performs.
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>{@value #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is
|
||||
* disabled.</li>
|
||||
* <li>{@value #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0
|
||||
* disables caching. Values larger than this are <em>not</em> cached.</li>
|
||||
* <li>{@value #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Here is a sample Maven invocation with caching disabled:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* mvn test -Dbcel.statistics=true -Dbcel.maxcached.size=0 -Dbcel.maxcached=0
|
||||
* </pre>
|
||||
* <p>
|
||||
* Here is a sample Maven invocation with caching enabled:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* mvn test -Dbcel.statistics=true -Dbcel.maxcached.size=100000 -Dbcel.maxcached=5000000
|
||||
* </pre>
|
||||
*
|
||||
* @see Constant
|
||||
* @LastModified: Jan 2020
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public final class ConstantUtf8 extends Constant {
|
||||
|
||||
@@ -42,8 +68,7 @@ public final class ConstantUtf8 extends Constant {
|
||||
private static final int MAX_ENTRIES = 20000;
|
||||
private static final int INITIAL_CAPACITY = (int) (MAX_ENTRIES / 0.75);
|
||||
|
||||
private static final HashMap<String, ConstantUtf8> CACHE = new LinkedHashMap<String, ConstantUtf8>(
|
||||
INITIAL_CAPACITY, 0.75f, true) {
|
||||
private static final HashMap<String, ConstantUtf8> CACHE = new LinkedHashMap<String, ConstantUtf8>(INITIAL_CAPACITY, 0.75f, true) {
|
||||
|
||||
private static final long serialVersionUID = -8506975356158971766L;
|
||||
|
||||
@@ -62,6 +87,22 @@ public final class ConstantUtf8 extends Constant {
|
||||
|
||||
}
|
||||
|
||||
// TODO these should perhaps be AtomicInt?
|
||||
private static volatile int considered;
|
||||
private static volatile int created;
|
||||
private static volatile int hits;
|
||||
private static volatile int skipped;
|
||||
|
||||
private static final String SYS_PROP_CACHE_MAX_ENTRIES = "bcel.maxcached";
|
||||
private static final String SYS_PROP_CACHE_MAX_ENTRY_SIZE = "bcel.maxcached.size";
|
||||
private static final String SYS_PROP_STATISTICS = "bcel.statistics";
|
||||
|
||||
static {
|
||||
if (Cache.BCEL_STATISTICS) {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(ConstantUtf8::printStats));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache.
|
||||
*
|
||||
@@ -71,6 +112,11 @@ public final class ConstantUtf8 extends Constant {
|
||||
Cache.CACHE.clear();
|
||||
}
|
||||
|
||||
// for access by test code
|
||||
static synchronized void clearStats() {
|
||||
hits = considered = skipped = created = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new or cached instance of the given value.
|
||||
* <p>
|
||||
@@ -83,12 +129,14 @@ public final class ConstantUtf8 extends Constant {
|
||||
*/
|
||||
public static ConstantUtf8 getCachedInstance(final String value) {
|
||||
if (value.length() > Cache.MAX_ENTRY_SIZE) {
|
||||
skipped++;
|
||||
return new ConstantUtf8(value);
|
||||
}
|
||||
|
||||
considered++;
|
||||
synchronized (ConstantUtf8.class) { // might be better with a specific lock object
|
||||
ConstantUtf8 result = Cache.CACHE.get(value);
|
||||
if (result != null) {
|
||||
hits++;
|
||||
return result;
|
||||
}
|
||||
result = new ConstantUtf8(value);
|
||||
@@ -126,6 +174,15 @@ public final class ConstantUtf8 extends Constant {
|
||||
return Cache.isEnabled() ? getCachedInstance(value) : new ConstantUtf8(value);
|
||||
}
|
||||
|
||||
// for access by test code
|
||||
static void printStats() {
|
||||
final String prefix = "[Apache Commons BCEL]";
|
||||
System.err.printf("%s Cache hit %,d/%,d, %d skipped.%n", prefix, hits, considered, skipped);
|
||||
System.err.printf("%s Total of %,d ConstantUtf8 objects created.%n", prefix, created);
|
||||
System.err.printf("%s Configuration: %s=%,d, %s=%,d.%n", prefix, SYS_PROP_CACHE_MAX_ENTRIES, Cache.MAX_ENTRIES, SYS_PROP_CACHE_MAX_ENTRY_SIZE,
|
||||
Cache.MAX_ENTRY_SIZE);
|
||||
}
|
||||
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
@@ -141,11 +198,12 @@ public final class ConstantUtf8 extends Constant {
|
||||
* Initializes instance from file data.
|
||||
*
|
||||
* @param dataInput Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantUtf8(final DataInput dataInput) throws IOException {
|
||||
super(Const.CONSTANT_Utf8);
|
||||
value = dataInput.readUTF();
|
||||
created++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,14 +211,12 @@ public final class ConstantUtf8 extends Constant {
|
||||
*/
|
||||
public ConstantUtf8(final String value) {
|
||||
super(Const.CONSTANT_Utf8);
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("Value must not be null.");
|
||||
}
|
||||
this.value = value;
|
||||
this.value = Objects.requireNonNull(value, "value");
|
||||
created++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
@@ -174,7 +230,7 @@ public final class ConstantUtf8 extends Constant {
|
||||
* Dumps String in Utf8 format to file stream.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
|
||||
@@ -26,81 +26,92 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and represents a constant
|
||||
* value, i.e., a default value for initializing a class field.
|
||||
* This class is instantiated by the <em>Attribute.readAttribute()</em> method.
|
||||
* This class is derived from <em>Attribute</em> and represents a constant value, i.e., a default value for initializing
|
||||
* a class field. This class is instantiated by the <em>Attribute.readAttribute()</em> method.
|
||||
*
|
||||
* @see Attribute
|
||||
* <pre>
|
||||
* ConstantValue_attribute {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u2 constantvalue_index;
|
||||
* }
|
||||
* </pre>
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class ConstantValue extends Attribute {
|
||||
|
||||
private int constantValueIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ConstantValue(final ConstantValue c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getConstantValueIndex(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* @param name_index Name index in constant pool
|
||||
*
|
||||
* @param nameIndex Name index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantValue(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, input.readUnsignedShort(), constant_pool);
|
||||
ConstantValue(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, input.readUnsignedShort(), constantPool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Name index in constant pool
|
||||
* @param nameIndex Name index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param constantValueIndex Index in constant pool
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public ConstantValue(final int name_index, final int length, final int constantValueIndex,
|
||||
final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_CONSTANT_VALUE, name_index, length, constant_pool);
|
||||
public ConstantValue(final int nameIndex, final int length, final int constantValueIndex, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_CONSTANT_VALUE, nameIndex, Args.require(length, 2, "ConstantValue attribute length"), constantPool);
|
||||
this.constantValueIndex = constantValueIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitConstantValue(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final ConstantValue c = (ConstantValue) clone();
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump constant value attribute to file stream on binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(constantValueIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of constant value.
|
||||
*/
|
||||
@@ -108,15 +119,13 @@ public final class ConstantValue extends Attribute {
|
||||
return constantValueIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param constantValueIndex the index info the constant pool of this constant value
|
||||
*/
|
||||
public void setConstantValueIndex( final int constantValueIndex ) {
|
||||
public void setConstantValueIndex(final int constantValueIndex) {
|
||||
this.constantValueIndex = constantValueIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation of constant value.
|
||||
*/
|
||||
@@ -127,37 +136,26 @@ public final class ConstantValue extends Attribute {
|
||||
int i;
|
||||
// Print constant to string depending on its type
|
||||
switch (c.getTag()) {
|
||||
case Const.CONSTANT_Long:
|
||||
buf = String.valueOf(((ConstantLong) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Float:
|
||||
buf = String.valueOf(((ConstantFloat) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Double:
|
||||
buf = String.valueOf(((ConstantDouble) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Integer:
|
||||
buf = String.valueOf(((ConstantInteger) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_String:
|
||||
i = ((ConstantString) c).getStringIndex();
|
||||
c = super.getConstantPool().getConstant(i, Const.CONSTANT_Utf8);
|
||||
buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\"";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Type of ConstValue invalid: " + c);
|
||||
case Const.CONSTANT_Long:
|
||||
buf = String.valueOf(((ConstantLong) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Float:
|
||||
buf = String.valueOf(((ConstantFloat) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Double:
|
||||
buf = String.valueOf(((ConstantDouble) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Integer:
|
||||
buf = String.valueOf(((ConstantInteger) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_String:
|
||||
i = ((ConstantString) c).getStringIndex();
|
||||
c = super.getConstantPool().getConstantUtf8(i);
|
||||
buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\"";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Type of ConstValue invalid: " + c);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final ConstantValue c = (ConstantValue) clone();
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,52 +25,50 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and denotes that this is a
|
||||
* deprecated method.
|
||||
* It is instantiated from the <em>Attribute.readAttribute()</em> method.
|
||||
* This class is derived from <em>Attribute</em> and denotes that this is a deprecated method. It is instantiated from
|
||||
* the <em>Attribute.readAttribute()</em> method.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class Deprecated extends Attribute {
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public Deprecated(final Deprecated c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param bytes Attribute contents
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public Deprecated(final int name_index, final int length, final byte[] bytes, final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_DEPRECATED, name_index, length, constant_pool);
|
||||
public Deprecated(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_DEPRECATED, nameIndex, Args.require0(length, "Deprecated attribute length"), constantPool);
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
Deprecated(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, (byte[]) null, constant_pool);
|
||||
Deprecated(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (byte[]) null, constantPool);
|
||||
if (length > 0) {
|
||||
bytes = new byte[length];
|
||||
input.readFully(bytes);
|
||||
@@ -78,35 +76,44 @@ public final class Deprecated extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitDeprecated(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final Deprecated c = (Deprecated) clone();
|
||||
if (bytes != null) {
|
||||
c.bytes = bytes.clone();
|
||||
}
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump source file attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
if (super.getLength() > 0) {
|
||||
file.write(bytes, 0, super.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return data bytes.
|
||||
*/
|
||||
@@ -114,35 +121,18 @@ public final class Deprecated extends Attribute {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represents this byte array
|
||||
*/
|
||||
public void setBytes( final byte[] bytes ) {
|
||||
public void setBytes(final byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return attribute name
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return Const.getAttributeName(Const.ATTR_DEPRECATED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final Deprecated c = (Deprecated) clone();
|
||||
if (bytes != null) {
|
||||
c.bytes = new byte[bytes.length];
|
||||
System.arraycopy(bytes, 0, c.bytes, 0, bytes.length);
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
return Const.getAttributeName(Const.ATTR_DEPRECATED) + ": true";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
*/
|
||||
package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Stack;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Traverses a JavaClass with another Visitor object 'piggy-backed' that is
|
||||
@@ -27,98 +29,67 @@ import java.util.Stack;
|
||||
* traversal strategy, other classes can make use of it.
|
||||
*
|
||||
*/
|
||||
public class DescendingVisitor implements Visitor
|
||||
{
|
||||
public class DescendingVisitor implements Visitor {
|
||||
private final JavaClass clazz;
|
||||
|
||||
private final Visitor visitor;
|
||||
|
||||
private final Stack<Object> stack = new Stack<>();
|
||||
|
||||
/**
|
||||
* @param clazz Class to traverse
|
||||
* @param visitor visitor object to apply to all components
|
||||
*/
|
||||
public DescendingVisitor(final JavaClass clazz, final Visitor visitor) {
|
||||
this.clazz = clazz;
|
||||
this.visitor = visitor;
|
||||
}
|
||||
|
||||
private <E extends Node> void accept(final E[] node) {
|
||||
Stream.of(node).forEach(e -> e.accept(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return current object
|
||||
*/
|
||||
public Object current() {
|
||||
return stack.peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return container of current entitity, i.e., predecessor during traversal
|
||||
*/
|
||||
public Object predecessor()
|
||||
{
|
||||
public Object predecessor() {
|
||||
return predecessor(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param level
|
||||
* nesting level, i.e., 0 returns the direct predecessor
|
||||
* @param level nesting level, i.e., 0 returns the direct predecessor
|
||||
* @return container of current entitity, i.e., predecessor during traversal
|
||||
*/
|
||||
public Object predecessor(final int level)
|
||||
{
|
||||
public Object predecessor(final int level) {
|
||||
final int size = stack.size();
|
||||
if ((size < 2) || (level < 0))
|
||||
{
|
||||
if (size < 2 || level < 0) {
|
||||
return null;
|
||||
}
|
||||
return stack.elementAt(size - (level + 2)); // size - 1 == current
|
||||
}
|
||||
|
||||
/**
|
||||
* @return current object
|
||||
*/
|
||||
public Object current()
|
||||
{
|
||||
return stack.peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clazz
|
||||
* Class to traverse
|
||||
* @param visitor
|
||||
* visitor object to apply to all components
|
||||
*/
|
||||
public DescendingVisitor(final JavaClass clazz, final Visitor visitor)
|
||||
{
|
||||
this.clazz = clazz;
|
||||
this.visitor = visitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start traversal.
|
||||
*/
|
||||
public void visit()
|
||||
{
|
||||
public void visit() {
|
||||
clazz.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJavaClass(final JavaClass _clazz)
|
||||
{
|
||||
stack.push(_clazz);
|
||||
_clazz.accept(visitor);
|
||||
final Field[] fields = _clazz.getFields();
|
||||
for (final Field field : fields) {
|
||||
field.accept(this);
|
||||
}
|
||||
final Method[] methods = _clazz.getMethods();
|
||||
for (final Method method : methods) {
|
||||
method.accept(this);
|
||||
}
|
||||
final Attribute[] attributes = _clazz.getAttributes();
|
||||
for (final Attribute attribute : attributes) {
|
||||
attribute.accept(this);
|
||||
}
|
||||
_clazz.getConstantPool().accept(this);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitAnnotation(final Annotations annotation)
|
||||
{
|
||||
public void visitAnnotation(final Annotations annotation) {
|
||||
stack.push(annotation);
|
||||
annotation.accept(visitor);
|
||||
final AnnotationEntry[] entries = annotation.getAnnotationEntries();
|
||||
for (final AnnotationEntry entrie : entries) {
|
||||
entrie.accept(this);
|
||||
}
|
||||
accept(annotation.getAnnotationEntries());
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@@ -126,197 +97,98 @@ public class DescendingVisitor implements Visitor
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitAnnotationEntry(final AnnotationEntry annotationEntry)
|
||||
{
|
||||
public void visitAnnotationDefault(final AnnotationDefault obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitAnnotationEntry(final AnnotationEntry annotationEntry) {
|
||||
stack.push(annotationEntry);
|
||||
annotationEntry.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitField(final Field field)
|
||||
{
|
||||
stack.push(field);
|
||||
field.accept(visitor);
|
||||
final Attribute[] attributes = field.getAttributes();
|
||||
for (final Attribute attribute : attributes) {
|
||||
attribute.accept(this);
|
||||
}
|
||||
public void visitBootstrapMethods(final BootstrapMethods bm) {
|
||||
stack.push(bm);
|
||||
bm.accept(visitor);
|
||||
// BootstrapMethod[] bms = bm.getBootstrapMethods();
|
||||
// for (int i = 0; i < bms.length; i++)
|
||||
// {
|
||||
// bms[i].accept(this);
|
||||
// }
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantValue(final ConstantValue cv)
|
||||
{
|
||||
stack.push(cv);
|
||||
cv.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(final Method method)
|
||||
{
|
||||
stack.push(method);
|
||||
method.accept(visitor);
|
||||
final Attribute[] attributes = method.getAttributes();
|
||||
for (final Attribute attribute : attributes) {
|
||||
attribute.accept(this);
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExceptionTable(final ExceptionTable table)
|
||||
{
|
||||
stack.push(table);
|
||||
table.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCode(final Code code)
|
||||
{
|
||||
public void visitCode(final Code code) {
|
||||
stack.push(code);
|
||||
code.accept(visitor);
|
||||
final CodeException[] table = code.getExceptionTable();
|
||||
for (final CodeException element : table) {
|
||||
element.accept(this);
|
||||
}
|
||||
final Attribute[] attributes = code.getAttributes();
|
||||
for (final Attribute attribute : attributes) {
|
||||
attribute.accept(this);
|
||||
}
|
||||
accept(code.getExceptionTable());
|
||||
accept(code.getAttributes());
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCodeException(final CodeException ce)
|
||||
{
|
||||
public void visitCodeException(final CodeException ce) {
|
||||
stack.push(ce);
|
||||
ce.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumberTable(final LineNumberTable table)
|
||||
{
|
||||
stack.push(table);
|
||||
table.accept(visitor);
|
||||
final LineNumber[] numbers = table.getLineNumberTable();
|
||||
for (final LineNumber number : numbers) {
|
||||
number.accept(this);
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumber(final LineNumber number)
|
||||
{
|
||||
stack.push(number);
|
||||
number.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariableTable(final LocalVariableTable table)
|
||||
{
|
||||
stack.push(table);
|
||||
table.accept(visitor);
|
||||
final LocalVariable[] vars = table.getLocalVariableTable();
|
||||
for (final LocalVariable var : vars) {
|
||||
var.accept(this);
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitStackMap(final StackMap table)
|
||||
{
|
||||
stack.push(table);
|
||||
table.accept(visitor);
|
||||
final StackMapEntry[] vars = table.getStackMap();
|
||||
for (final StackMapEntry var : vars) {
|
||||
var.accept(this);
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitStackMapEntry(final StackMapEntry var)
|
||||
{
|
||||
stack.push(var);
|
||||
var.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(final LocalVariable var)
|
||||
{
|
||||
stack.push(var);
|
||||
var.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantPool(final ConstantPool cp)
|
||||
{
|
||||
stack.push(cp);
|
||||
cp.accept(visitor);
|
||||
final Constant[] constants = cp.getConstantPool();
|
||||
for (int i = 1; i < constants.length; i++)
|
||||
{
|
||||
if (constants[i] != null)
|
||||
{
|
||||
constants[i].accept(this);
|
||||
}
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantClass(final ConstantClass constant)
|
||||
{
|
||||
public void visitConstantClass(final ConstantClass constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantDouble(final ConstantDouble constant)
|
||||
{
|
||||
public void visitConstantDouble(final ConstantDouble constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.3 */
|
||||
@Override
|
||||
public void visitConstantDynamic(final ConstantDynamic obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantFieldref(final ConstantFieldref constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantFieldref(final ConstantFieldref constant)
|
||||
{
|
||||
public void visitConstantFloat(final ConstantFloat constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantFloat(final ConstantFloat constant)
|
||||
{
|
||||
public void visitConstantInteger(final ConstantInteger constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantInteger(final ConstantInteger constant)
|
||||
{
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantInterfaceMethodref(
|
||||
final ConstantInterfaceMethodref constant)
|
||||
{
|
||||
public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
@@ -326,208 +198,19 @@ public class DescendingVisitor implements Visitor
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantInvokeDynamic(
|
||||
final ConstantInvokeDynamic constant)
|
||||
{
|
||||
public void visitConstantInvokeDynamic(final ConstantInvokeDynamic constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantLong(final ConstantLong constant)
|
||||
{
|
||||
public void visitConstantLong(final ConstantLong constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantMethodref(final ConstantMethodref constant)
|
||||
{
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantNameAndType(final ConstantNameAndType constant)
|
||||
{
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantString(final ConstantString constant)
|
||||
{
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantUtf8(final ConstantUtf8 constant)
|
||||
{
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClasses(final InnerClasses ic)
|
||||
{
|
||||
stack.push(ic);
|
||||
ic.accept(visitor);
|
||||
final InnerClass[] ics = ic.getInnerClasses();
|
||||
for (final InnerClass ic2 : ics) {
|
||||
ic2.accept(this);
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(final InnerClass inner)
|
||||
{
|
||||
stack.push(inner);
|
||||
inner.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitBootstrapMethods(final BootstrapMethods bm)
|
||||
{
|
||||
stack.push(bm);
|
||||
bm.accept(visitor);
|
||||
// BootstrapMethod[] bms = bm.getBootstrapMethods();
|
||||
// for (int i = 0; i < bms.length; i++)
|
||||
// {
|
||||
// bms[i].accept(this);
|
||||
// }
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDeprecated(final Deprecated attribute)
|
||||
{
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSignature(final Signature attribute)
|
||||
{
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSourceFile(final SourceFile attribute)
|
||||
{
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSynthetic(final Synthetic attribute)
|
||||
{
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitUnknown(final Unknown attribute)
|
||||
{
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitAnnotationDefault(final AnnotationDefault obj)
|
||||
{
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitEnclosingMethod(final EnclosingMethod obj)
|
||||
{
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj)
|
||||
{
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitParameterAnnotation(final ParameterAnnotations obj)
|
||||
{
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitMethodParameters(final MethodParameters obj)
|
||||
{
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
final MethodParameter[] table = obj.getParameters();
|
||||
for (final MethodParameter element : table) {
|
||||
element.accept(this);
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitMethodParameter(final MethodParameter obj)
|
||||
{
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
@Override
|
||||
public void visitConstantMethodType(final ConstantMethodType obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
@Override
|
||||
public void visitConstantMethodHandle(final ConstantMethodHandle obj) {
|
||||
@@ -536,17 +219,16 @@ public class DescendingVisitor implements Visitor
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
@Override
|
||||
public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
public void visitConstantMethodref(final ConstantMethodref constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.1 */
|
||||
/** @since 6.0 */
|
||||
@Override
|
||||
public void visitConstantPackage(final ConstantPackage obj) {
|
||||
public void visitConstantMethodType(final ConstantMethodType obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
@@ -560,41 +242,192 @@ public class DescendingVisitor implements Visitor
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.3 */
|
||||
@Override
|
||||
public void visitConstantDynamic(final ConstantDynamic obj) {
|
||||
public void visitConstantNameAndType(final ConstantNameAndType constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.1 */
|
||||
@Override
|
||||
public void visitConstantPackage(final ConstantPackage obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantPool(final ConstantPool cp) {
|
||||
stack.push(cp);
|
||||
cp.accept(visitor);
|
||||
Stream.of(cp.getConstantPool()).filter(Objects::nonNull).forEach(e -> e.accept(this));
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantString(final ConstantString constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantUtf8(final ConstantUtf8 constant) {
|
||||
stack.push(constant);
|
||||
constant.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantValue(final ConstantValue cv) {
|
||||
stack.push(cv);
|
||||
cv.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDeprecated(final Deprecated attribute) {
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitEnclosingMethod(final EnclosingMethod obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExceptionTable(final ExceptionTable table) {
|
||||
stack.push(table);
|
||||
table.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitField(final Field field) {
|
||||
stack.push(field);
|
||||
field.accept(visitor);
|
||||
accept(field.getAttributes());
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(final InnerClass inner) {
|
||||
stack.push(inner);
|
||||
inner.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClasses(final InnerClasses ic) {
|
||||
stack.push(ic);
|
||||
ic.accept(visitor);
|
||||
accept(ic.getInnerClasses());
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJavaClass(final JavaClass clazz) {
|
||||
stack.push(clazz);
|
||||
clazz.accept(visitor);
|
||||
accept(clazz.getFields());
|
||||
accept(clazz.getMethods());
|
||||
accept(clazz.getAttributes());
|
||||
clazz.getConstantPool().accept(this);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumber(final LineNumber number) {
|
||||
stack.push(number);
|
||||
number.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumberTable(final LineNumberTable table) {
|
||||
stack.push(table);
|
||||
table.accept(visitor);
|
||||
accept(table.getLineNumberTable());
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(final LocalVariable var) {
|
||||
stack.push(var);
|
||||
var.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariableTable(final LocalVariableTable table) {
|
||||
stack.push(table);
|
||||
table.accept(visitor);
|
||||
accept(table.getLocalVariableTable());
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(final Method method) {
|
||||
stack.push(method);
|
||||
method.accept(visitor);
|
||||
accept(method.getAttributes());
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitMethodParameter(final MethodParameter obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitMethodParameters(final MethodParameters obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
Stream.of(obj.getParameters()).forEach(e -> e.accept(this));
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModule(final Module obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
final ModuleRequires[] rtable = obj.getRequiresTable();
|
||||
for (final ModuleRequires element : rtable) {
|
||||
element.accept(this);
|
||||
}
|
||||
final ModuleExports[] etable = obj.getExportsTable();
|
||||
for (final ModuleExports element : etable) {
|
||||
element.accept(this);
|
||||
}
|
||||
final ModuleOpens[] otable = obj.getOpensTable();
|
||||
for (final ModuleOpens element : otable) {
|
||||
element.accept(this);
|
||||
}
|
||||
final ModuleProvides[] ptable = obj.getProvidesTable();
|
||||
for (final ModuleProvides element : ptable) {
|
||||
element.accept(this);
|
||||
}
|
||||
accept(obj.getRequiresTable());
|
||||
accept(obj.getExportsTable());
|
||||
accept(obj.getOpensTable());
|
||||
accept(obj.getProvidesTable());
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleRequires(final ModuleRequires obj) {
|
||||
public void visitModuleExports(final ModuleExports obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
@@ -602,7 +435,7 @@ public class DescendingVisitor implements Visitor
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleExports(final ModuleExports obj) {
|
||||
public void visitModuleMainClass(final ModuleMainClass obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
@@ -616,14 +449,6 @@ public class DescendingVisitor implements Visitor
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleProvides(final ModuleProvides obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModulePackages(final ModulePackages obj) {
|
||||
@@ -634,7 +459,15 @@ public class DescendingVisitor implements Visitor
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleMainClass(final ModuleMainClass obj) {
|
||||
public void visitModuleProvides(final ModuleProvides obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleRequires(final ModuleRequires obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
@@ -655,4 +488,65 @@ public class DescendingVisitor implements Visitor
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitParameterAnnotation(final ParameterAnnotations obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
@Override
|
||||
public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSignature(final Signature attribute) {
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSourceFile(final SourceFile attribute) {
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitStackMap(final StackMap table) {
|
||||
stack.push(table);
|
||||
table.accept(visitor);
|
||||
accept(table.getStackMap());
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitStackMapEntry(final StackMapEntry var) {
|
||||
stack.push(var);
|
||||
var.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSynthetic(final Synthetic attribute) {
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitUnknown(final Unknown attribute) {
|
||||
stack.push(attribute);
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,103 +24,155 @@ import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* The element_value structure is documented at https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7.16.1
|
||||
*
|
||||
* <pre>
|
||||
* element_value {
|
||||
* u1 tag;
|
||||
* union {
|
||||
* u2 const_value_index;
|
||||
*
|
||||
* { u2 type_name_index;
|
||||
* u2 const_name_index;
|
||||
* } enum_const_value;
|
||||
*
|
||||
* u2 class_info_index;
|
||||
*
|
||||
* annotation annotation_value;
|
||||
*
|
||||
* { u2 num_values;
|
||||
* element_value values[num_values];
|
||||
* } array_value;
|
||||
* } value;
|
||||
*}
|
||||
*</pre>
|
||||
* @since 6.0
|
||||
* @LastModified: May 2021
|
||||
*/
|
||||
public abstract class ElementValue
|
||||
{
|
||||
private final int type;
|
||||
public abstract class ElementValue {
|
||||
|
||||
private final ConstantPool cpool;
|
||||
public static final byte STRING = 's';
|
||||
public static final byte ENUM_CONSTANT = 'e';
|
||||
public static final byte CLASS = 'c';
|
||||
public static final byte ANNOTATION = '@';
|
||||
public static final byte ARRAY = '[';
|
||||
public static final byte PRIMITIVE_INT = 'I';
|
||||
public static final byte PRIMITIVE_BYTE = 'B';
|
||||
public static final byte PRIMITIVE_CHAR = 'C';
|
||||
public static final byte PRIMITIVE_DOUBLE = 'D';
|
||||
public static final byte PRIMITIVE_FLOAT = 'F';
|
||||
public static final byte PRIMITIVE_LONG = 'J';
|
||||
public static final byte PRIMITIVE_SHORT = 'S';
|
||||
public static final byte PRIMITIVE_BOOLEAN = 'Z';
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return stringifyValue();
|
||||
/**
|
||||
* Reads an {@code element_value} as an {@code ElementValue}.
|
||||
*
|
||||
* @param input Raw data input.
|
||||
* @param cpool Constant pool.
|
||||
* @return a new ElementValue.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool) throws IOException {
|
||||
return readElementValue(input, cpool, 0);
|
||||
}
|
||||
|
||||
protected ElementValue(final int type, final ConstantPool cpool)
|
||||
{
|
||||
/**
|
||||
* Reads an {@code element_value} as an {@code ElementValue}.
|
||||
*
|
||||
* @param input Raw data input.
|
||||
* @param cpool Constant pool.
|
||||
* @param arrayNesting level of current array nesting.
|
||||
* @return a new ElementValue.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @since 6.7.0
|
||||
*/
|
||||
public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool, int arrayNesting)
|
||||
throws IOException {
|
||||
final byte tag = input.readByte();
|
||||
switch (tag) {
|
||||
case PRIMITIVE_BYTE:
|
||||
case PRIMITIVE_CHAR:
|
||||
case PRIMITIVE_DOUBLE:
|
||||
case PRIMITIVE_FLOAT:
|
||||
case PRIMITIVE_INT:
|
||||
case PRIMITIVE_LONG:
|
||||
case PRIMITIVE_SHORT:
|
||||
case PRIMITIVE_BOOLEAN:
|
||||
case STRING:
|
||||
return new SimpleElementValue(tag, input.readUnsignedShort(), cpool);
|
||||
|
||||
case ENUM_CONSTANT:
|
||||
return new EnumElementValue(ENUM_CONSTANT, input.readUnsignedShort(), input.readUnsignedShort(), cpool);
|
||||
|
||||
case CLASS:
|
||||
return new ClassElementValue(CLASS, input.readUnsignedShort(), cpool);
|
||||
|
||||
case ANNOTATION:
|
||||
// TODO isRuntimeVisible
|
||||
return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read(input, cpool, false), cpool);
|
||||
|
||||
case ARRAY:
|
||||
arrayNesting++;
|
||||
if (arrayNesting > Const.MAX_ARRAY_DIMENSIONS) {
|
||||
// JVM spec 4.4.1
|
||||
throw new ClassFormatException(String.format("Arrays are only valid if they represent %,d or fewer dimensions.", Const.MAX_ARRAY_DIMENSIONS));
|
||||
}
|
||||
final int numArrayVals = input.readUnsignedShort();
|
||||
final ElementValue[] evalues = new ElementValue[numArrayVals];
|
||||
for (int j = 0; j < numArrayVals; j++) {
|
||||
evalues[j] = ElementValue.readElementValue(input, cpool, arrayNesting);
|
||||
}
|
||||
return new ArrayElementValue(ARRAY, evalues, cpool);
|
||||
|
||||
default:
|
||||
throw new ClassFormatException("Unexpected element value tag in annotation: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private and final; do not access directly, use getter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int type; // TODO should be final
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private and final; do not access directly, use getter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected ConstantPool cpool; // TODO should be final
|
||||
|
||||
protected ElementValue(final int type, final ConstantPool cpool) {
|
||||
this.type = type;
|
||||
this.cpool = cpool;
|
||||
}
|
||||
|
||||
public int getElementValueType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public abstract String stringifyValue();
|
||||
|
||||
public abstract void dump(DataOutputStream dos) throws IOException;
|
||||
|
||||
public static final byte STRING = 's';
|
||||
public static final byte ENUM_CONSTANT = 'e';
|
||||
public static final byte CLASS = 'c';
|
||||
public static final byte ANNOTATION = '@';
|
||||
public static final byte ARRAY = '[';
|
||||
public static final byte PRIMITIVE_INT = 'I';
|
||||
public static final byte PRIMITIVE_BYTE = 'B';
|
||||
public static final byte PRIMITIVE_CHAR = 'C';
|
||||
public static final byte PRIMITIVE_DOUBLE = 'D';
|
||||
public static final byte PRIMITIVE_FLOAT = 'F';
|
||||
public static final byte PRIMITIVE_LONG = 'J';
|
||||
public static final byte PRIMITIVE_SHORT = 'S';
|
||||
public static final byte PRIMITIVE_BOOLEAN = 'Z';
|
||||
|
||||
public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool) throws IOException
|
||||
{
|
||||
final byte type = input.readByte();
|
||||
switch (type)
|
||||
{
|
||||
case PRIMITIVE_BYTE:
|
||||
case PRIMITIVE_CHAR:
|
||||
case PRIMITIVE_DOUBLE:
|
||||
case PRIMITIVE_FLOAT:
|
||||
case PRIMITIVE_INT:
|
||||
case PRIMITIVE_LONG:
|
||||
case PRIMITIVE_SHORT:
|
||||
case PRIMITIVE_BOOLEAN:
|
||||
case STRING:
|
||||
return new SimpleElementValue(type, input.readUnsignedShort(), cpool);
|
||||
|
||||
case ENUM_CONSTANT:
|
||||
return new EnumElementValue(ENUM_CONSTANT, input.readUnsignedShort(), input.readUnsignedShort(), cpool);
|
||||
|
||||
case CLASS:
|
||||
return new ClassElementValue(CLASS, input.readUnsignedShort(), cpool);
|
||||
|
||||
case ANNOTATION:
|
||||
// TODO isRuntimeVisible
|
||||
return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read(input, cpool, false), cpool);
|
||||
|
||||
case ARRAY:
|
||||
final int numArrayVals = input.readUnsignedShort();
|
||||
final ElementValue[] evalues = new ElementValue[numArrayVals];
|
||||
for (int j = 0; j < numArrayVals; j++)
|
||||
{
|
||||
evalues[j] = ElementValue.readElementValue(input, cpool);
|
||||
}
|
||||
return new ArrayElementValue(ARRAY, evalues, cpool);
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Unexpected element value kind in annotation: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
final ConstantPool getConstantPool() {
|
||||
return cpool;
|
||||
}
|
||||
|
||||
public int getElementValueType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
final int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String toShortString()
|
||||
{
|
||||
public abstract String stringifyValue();
|
||||
|
||||
public String toShortString() {
|
||||
return stringifyValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return stringifyValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,56 +24,47 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* an annotation's element value pair
|
||||
* An annotation's element value pair.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class ElementValuePair
|
||||
{
|
||||
public class ElementValuePair {
|
||||
|
||||
static final ElementValuePair[] EMPTY_ARRAY = {};
|
||||
|
||||
private final ElementValue elementValue;
|
||||
|
||||
private final ConstantPool constantPool;
|
||||
|
||||
private final int elementNameIndex;
|
||||
|
||||
public ElementValuePair(final int elementNameIndex, final ElementValue elementValue,
|
||||
final ConstantPool constantPool)
|
||||
{
|
||||
public ElementValuePair(final int elementNameIndex, final ElementValue elementValue, final ConstantPool constantPool) {
|
||||
this.elementValue = elementValue;
|
||||
this.elementNameIndex = elementNameIndex;
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
public String getNameString()
|
||||
{
|
||||
final ConstantUtf8 c = (ConstantUtf8) constantPool.getConstant(
|
||||
elementNameIndex, Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
}
|
||||
|
||||
public final ElementValue getValue()
|
||||
{
|
||||
return elementValue;
|
||||
}
|
||||
|
||||
public int getNameIndex()
|
||||
{
|
||||
return elementNameIndex;
|
||||
}
|
||||
|
||||
public String toShortString()
|
||||
{
|
||||
final StringBuilder result = new StringBuilder();
|
||||
result.append(getNameString()).append("=").append(
|
||||
getValue().toShortString());
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
protected void dump(final DataOutputStream dos) throws IOException {
|
||||
dos.writeShort(elementNameIndex); // u2 name of the element
|
||||
elementValue.dump(dos);
|
||||
}
|
||||
|
||||
public int getNameIndex() {
|
||||
return elementNameIndex;
|
||||
}
|
||||
|
||||
public String getNameString() {
|
||||
return constantPool.getConstantUtf8(elementNameIndex).getBytes();
|
||||
}
|
||||
|
||||
public final ElementValue getValue() {
|
||||
return elementValue;
|
||||
}
|
||||
|
||||
public String toShortString() {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
result.append(getNameString()).append("=").append(getValue().toShortString());
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,304 +22,57 @@
|
||||
package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
/**
|
||||
* Visitor with empty method bodies, can be extended and used in conjunction
|
||||
* with the DescendingVisitor class, e.g. By courtesy of David Spencer.
|
||||
* Visitor with empty method bodies, can be extended and used in conjunction with the DescendingVisitor class, e.g. By
|
||||
* courtesy of David Spencer.
|
||||
*
|
||||
* @see DescendingVisitor
|
||||
*/
|
||||
public class EmptyVisitor implements Visitor
|
||||
{
|
||||
protected EmptyVisitor()
|
||||
{
|
||||
public class EmptyVisitor implements Visitor {
|
||||
protected EmptyVisitor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitAnnotation(final Annotations obj)
|
||||
{
|
||||
public void visitAnnotation(final Annotations obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitParameterAnnotation(final ParameterAnnotations obj)
|
||||
{
|
||||
public void visitAnnotationDefault(final AnnotationDefault obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitAnnotationEntry(final AnnotationEntry obj)
|
||||
{
|
||||
public void visitAnnotationEntry(final AnnotationEntry obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitAnnotationDefault(final AnnotationDefault obj)
|
||||
{
|
||||
public void visitBootstrapMethods(final BootstrapMethods obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCode(final Code obj)
|
||||
{
|
||||
public void visitCode(final Code obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCodeException(final CodeException obj)
|
||||
{
|
||||
public void visitCodeException(final CodeException obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantClass(final ConstantClass obj)
|
||||
{
|
||||
public void visitConstantClass(final ConstantClass obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantDouble(final ConstantDouble obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantFieldref(final ConstantFieldref obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantFloat(final ConstantFloat obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantInteger(final ConstantInteger obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantInvokeDynamic(final ConstantInvokeDynamic obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantLong(final ConstantLong obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantMethodref(final ConstantMethodref obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantNameAndType(final ConstantNameAndType obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantPool(final ConstantPool obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantString(final ConstantString obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantUtf8(final ConstantUtf8 obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantValue(final ConstantValue obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDeprecated(final Deprecated obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExceptionTable(final ExceptionTable obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitField(final Field obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(final InnerClass obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClasses(final InnerClasses obj)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitBootstrapMethods(final BootstrapMethods obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJavaClass(final JavaClass obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumber(final LineNumber obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumberTable(final LineNumberTable obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(final LocalVariable obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariableTable(final LocalVariableTable obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(final Method obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSignature(final Signature obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSourceFile(final SourceFile obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSynthetic(final Synthetic obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitUnknown(final Unknown obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitStackMap(final StackMap obj)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitStackMapEntry(final StackMapEntry obj)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
@Override
|
||||
public void visitStackMapTable(StackMapTable obj)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
@Override
|
||||
public void visitStackMapTableEntry(StackMapTableEntry obj)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitEnclosingMethod(final EnclosingMethod obj)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitMethodParameters(final MethodParameters obj)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitMethodParameter(final MethodParameter obj)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantMethodType(final ConstantMethodType obj)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantMethodHandle(final ConstantMethodHandle constantMethodHandle) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitParameterAnnotationEntry(final ParameterAnnotationEntry parameterAnnotationEntry) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantPackage(final ConstantPackage constantPackage) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantModule(final ConstantModule constantModule) {
|
||||
public void visitConstantDouble(final ConstantDouble obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,14 +82,167 @@ public class EmptyVisitor implements Visitor
|
||||
public void visitConstantDynamic(final ConstantDynamic obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModule(final Module obj) {
|
||||
public void visitConstantFieldref(final ConstantFieldref obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantFloat(final ConstantFloat obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantInteger(final ConstantInteger obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantInvokeDynamic(final ConstantInvokeDynamic obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantLong(final ConstantLong obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantMethodHandle(final ConstantMethodHandle constantMethodHandle) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantMethodref(final ConstantMethodref obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantMethodType(final ConstantMethodType obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantModule(final ConstantModule constantModule) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantNameAndType(final ConstantNameAndType obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantPackage(final ConstantPackage constantPackage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantPool(final ConstantPool obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantString(final ConstantString obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantUtf8(final ConstantUtf8 obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantValue(final ConstantValue obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDeprecated(final Deprecated obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitEnclosingMethod(final EnclosingMethod obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExceptionTable(final ExceptionTable obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitField(final Field obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(final InnerClass obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClasses(final InnerClasses obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJavaClass(final JavaClass obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumber(final LineNumber obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumberTable(final LineNumberTable obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(final LocalVariable obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariableTable(final LocalVariableTable obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(final Method obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
* @Override public void visitStackMapTable(StackMapTable obj) { }
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
* @Override public void visitStackMapTableEntry(StackMapTableEntry obj) { }
|
||||
*/
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitMethodParameter(final MethodParameter obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitMethodParameters(final MethodParameters obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleRequires(final ModuleRequires obj) {
|
||||
public void visitModule(final Module obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@@ -346,12 +252,12 @@ public class EmptyVisitor implements Visitor
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleOpens(final ModuleOpens obj) {
|
||||
public void visitModuleMainClass(final ModuleMainClass obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleProvides(final ModuleProvides obj) {
|
||||
public void visitModuleOpens(final ModuleOpens obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@@ -361,7 +267,12 @@ public class EmptyVisitor implements Visitor
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleMainClass(final ModuleMainClass obj) {
|
||||
public void visitModuleProvides(final ModuleProvides obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@Override
|
||||
public void visitModuleRequires(final ModuleRequires obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
@@ -373,4 +284,42 @@ public class EmptyVisitor implements Visitor
|
||||
@Override
|
||||
public void visitNestMembers(final NestMembers obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitParameterAnnotation(final ParameterAnnotations obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitParameterAnnotationEntry(final ParameterAnnotationEntry parameterAnnotationEntry) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSignature(final Signature obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSourceFile(final SourceFile obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitStackMap(final StackMap obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitStackMapEntry(final StackMapEntry obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSynthetic(final Synthetic obj) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitUnknown(final Unknown obj) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,10 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This attribute exists for local or
|
||||
* anonymous classes and ... there can be only one.
|
||||
* This attribute exists for local or anonymous classes and ... there can be only one.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
@@ -41,10 +41,10 @@ public class EnclosingMethod extends Attribute {
|
||||
|
||||
// If the current class is not immediately enclosed by a method or
|
||||
// constructor, then the value of the method_index item must be zero.
|
||||
// Otherwise, the value of the method_index item must point to a
|
||||
// Otherwise, the value of the method_index item must point to a
|
||||
// CONSTANT_NameAndType_info structure representing the name and the
|
||||
// type of a method in the class referenced by the class we point
|
||||
// to in the class_index. *It is the compiler responsibility* to
|
||||
// to in the class_index. *It is the compiler responsibility* to
|
||||
// ensure that the method identified by this index is the closest
|
||||
// lexically enclosing method that includes the local/anonymous class.
|
||||
private int methodIndex;
|
||||
@@ -54,27 +54,45 @@ public class EnclosingMethod extends Attribute {
|
||||
this(nameIndex, len, input.readUnsignedShort(), input.readUnsignedShort(), cpool);
|
||||
}
|
||||
|
||||
private EnclosingMethod(final int nameIndex, final int len, final int classIdx,final int methodIdx, final ConstantPool cpool) {
|
||||
super(Const.ATTR_ENCLOSING_METHOD, nameIndex, len, cpool);
|
||||
classIndex = classIdx;
|
||||
methodIndex = methodIdx;
|
||||
private EnclosingMethod(final int nameIndex, final int len, final int classIndex, final int methodIndex, final ConstantPool cpool) {
|
||||
super(Const.ATTR_ENCLOSING_METHOD, nameIndex, Args.require(len, 4, "EnclosingMethod attribute length"), cpool);
|
||||
this.classIndex = Args.requireU2(classIndex, 0, cpool.getLength(), "EnclosingMethod class index");
|
||||
this.methodIndex = Args.requireU2(methodIndex, "EnclosingMethod method index");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(final Visitor v) {
|
||||
v.visitEnclosingMethod(this);
|
||||
v.visitEnclosingMethod(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constant_pool) {
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(classIndex);
|
||||
file.writeShort(methodIndex);
|
||||
}
|
||||
|
||||
public final ConstantClass getEnclosingClass() {
|
||||
return super.getConstantPool().getConstant(classIndex, Const.CONSTANT_Class, ConstantClass.class);
|
||||
}
|
||||
|
||||
// Accessors
|
||||
public final int getEnclosingClassIndex() {
|
||||
return classIndex;
|
||||
}
|
||||
|
||||
public final ConstantNameAndType getEnclosingMethod() {
|
||||
if (methodIndex == 0) {
|
||||
return null;
|
||||
}
|
||||
return super.getConstantPool().getConstant(methodIndex, Const.CONSTANT_NameAndType, ConstantNameAndType.class);
|
||||
}
|
||||
|
||||
public final int getEnclosingMethodIndex() {
|
||||
return methodIndex;
|
||||
}
|
||||
@@ -86,26 +104,4 @@ public class EnclosingMethod extends Attribute {
|
||||
public final void setEnclosingMethodIndex(final int idx) {
|
||||
methodIndex = idx;
|
||||
}
|
||||
|
||||
public final ConstantClass getEnclosingClass() {
|
||||
final ConstantClass c =
|
||||
(ConstantClass)super.getConstantPool().getConstant(classIndex,Const.CONSTANT_Class);
|
||||
return c;
|
||||
}
|
||||
|
||||
public final ConstantNameAndType getEnclosingMethod() {
|
||||
if (methodIndex == 0) {
|
||||
return null;
|
||||
}
|
||||
final ConstantNameAndType nat =
|
||||
(ConstantNameAndType)super.getConstantPool().getConstant(methodIndex,Const.CONSTANT_NameAndType);
|
||||
return nat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(classIndex);
|
||||
file.writeShort(methodIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,67 +24,49 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
public class EnumElementValue extends ElementValue
|
||||
{
|
||||
public class EnumElementValue extends ElementValue {
|
||||
// For enum types, these two indices point to the type and value
|
||||
private final int typeIdx;
|
||||
|
||||
private final int valueIdx;
|
||||
|
||||
public EnumElementValue(final int type, final int typeIdx, final int valueIdx,
|
||||
final ConstantPool cpool)
|
||||
{
|
||||
public EnumElementValue(final int type, final int typeIdx, final int valueIdx, final ConstantPool cpool) {
|
||||
super(type, cpool);
|
||||
if (type != ENUM_CONSTANT) {
|
||||
throw new IllegalArgumentException(
|
||||
"Only element values of type enum can be built with this ctor - type specified: " + type);
|
||||
throw new ClassFormatException("Only element values of type enum can be built with this ctor - type specified: " + type);
|
||||
}
|
||||
this.typeIdx = typeIdx;
|
||||
this.valueIdx = valueIdx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(final DataOutputStream dos) throws IOException
|
||||
{
|
||||
public void dump(final DataOutputStream dos) throws IOException {
|
||||
dos.writeByte(super.getType()); // u1 type of value (ENUM_CONSTANT == 'e')
|
||||
dos.writeShort(typeIdx); // u2
|
||||
dos.writeShort(valueIdx); // u2
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringifyValue()
|
||||
{
|
||||
final ConstantUtf8 cu8 = (ConstantUtf8) super.getConstantPool().getConstant(valueIdx,
|
||||
Const.CONSTANT_Utf8);
|
||||
return cu8.getBytes();
|
||||
public String getEnumTypeString() {
|
||||
return super.getConstantPool().getConstantUtf8(typeIdx).getBytes();
|
||||
}
|
||||
|
||||
public String getEnumTypeString()
|
||||
{
|
||||
final ConstantUtf8 cu8 = (ConstantUtf8) super.getConstantPool().getConstant(typeIdx,
|
||||
Const.CONSTANT_Utf8);
|
||||
return cu8.getBytes();// Utility.signatureToString(cu8.getBytes());
|
||||
public String getEnumValueString() {
|
||||
return super.getConstantPool().getConstantUtf8(valueIdx).getBytes();
|
||||
}
|
||||
|
||||
public String getEnumValueString()
|
||||
{
|
||||
final ConstantUtf8 cu8 = (ConstantUtf8) super.getConstantPool().getConstant(valueIdx,
|
||||
Const.CONSTANT_Utf8);
|
||||
return cu8.getBytes();
|
||||
public int getTypeIndex() {
|
||||
return typeIdx;
|
||||
}
|
||||
|
||||
public int getValueIndex()
|
||||
{
|
||||
public int getValueIndex() {
|
||||
return valueIdx;
|
||||
}
|
||||
|
||||
public int getTypeIndex()
|
||||
{
|
||||
return typeIdx;
|
||||
@Override
|
||||
public String stringifyValue() {
|
||||
return super.getConstantPool().getConstantUtf8(valueIdx).getBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -24,85 +23,104 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class represents the table of exceptions that are thrown by a
|
||||
* method. This attribute may be used once per method. The name of
|
||||
* this class is <em>ExceptionTable</em> for historical reasons; The
|
||||
* Java Virtual Machine Specification, Second Edition defines this
|
||||
* attribute using the name <em>Exceptions</em> (which is inconsistent
|
||||
* with the other classes).
|
||||
* This class represents the table of exceptions that are thrown by a method. This attribute may be used once per
|
||||
* method. The name of this class is <em>ExceptionTable</em> for historical reasons; The Java Virtual Machine
|
||||
* Specification, Second Edition defines this attribute using the name <em>Exceptions</em> (which is inconsistent with
|
||||
* the other classes).
|
||||
*
|
||||
* @see Code
|
||||
* <pre>
|
||||
* Exceptions_attribute {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u2 number_of_exceptions;
|
||||
* u2 exception_index_table[number_of_exceptions];
|
||||
* }
|
||||
* </pre>
|
||||
* @see Code
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public final class ExceptionTable extends Attribute {
|
||||
|
||||
private int[] exceptionIndexTable; // constant pool
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ExceptionTable(final ExceptionTable c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getExceptionIndexTable(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param exceptionIndexTable Table of indices in constant pool
|
||||
* @param constant_pool Array of constants
|
||||
*/
|
||||
public ExceptionTable(final int name_index, final int length, final int[] exceptionIndexTable,
|
||||
final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_EXCEPTIONS, name_index, length, constant_pool);
|
||||
this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : new int[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ExceptionTable(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (int[]) null, constantPool);
|
||||
final int number_of_exceptions = input.readUnsignedShort();
|
||||
exceptionIndexTable = new int[number_of_exceptions];
|
||||
for (int i = 0; i < number_of_exceptions; i++) {
|
||||
final int exceptionCount = input.readUnsignedShort();
|
||||
exceptionIndexTable = new int[exceptionCount];
|
||||
for (int i = 0; i < exceptionCount; i++) {
|
||||
exceptionIndexTable[i] = input.readUnsignedShort();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param exceptionIndexTable Table of indices in constant pool
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public ExceptionTable(final int nameIndex, final int length, final int[] exceptionIndexTable, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_EXCEPTIONS, nameIndex, length, constantPool);
|
||||
this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY;
|
||||
Args.requireU2(this.exceptionIndexTable.length, "exceptionIndexTable.length");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitExceptionTable(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final ExceptionTable c = (ExceptionTable) clone();
|
||||
if (exceptionIndexTable != null) {
|
||||
c.exceptionIndexTable = exceptionIndexTable.clone();
|
||||
}
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump exceptions attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(exceptionIndexTable.length);
|
||||
for (final int index : exceptionIndexTable) {
|
||||
@@ -110,7 +128,6 @@ public final class ExceptionTable extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Array of indices into constant pool of thrown exceptions.
|
||||
*/
|
||||
@@ -118,6 +135,14 @@ public final class ExceptionTable extends Attribute {
|
||||
return exceptionIndexTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class names of thrown exceptions
|
||||
*/
|
||||
public String[] getExceptionNames() {
|
||||
final String[] names = new String[exceptionIndexTable.length];
|
||||
Arrays.setAll(names, i -> Utility.pathToPackage(super.getConstantPool().getConstantString(exceptionIndexTable[i], Const.CONSTANT_Class)));
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Length of exception table.
|
||||
@@ -126,29 +151,14 @@ public final class ExceptionTable extends Attribute {
|
||||
return exceptionIndexTable == null ? 0 : exceptionIndexTable.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return class names of thrown exceptions
|
||||
* @param exceptionIndexTable the list of exception indexes Also redefines number_of_exceptions according to table
|
||||
* length.
|
||||
*/
|
||||
public String[] getExceptionNames() {
|
||||
final String[] names = new String[exceptionIndexTable.length];
|
||||
for (int i = 0; i < exceptionIndexTable.length; i++) {
|
||||
names[i] = super.getConstantPool().getConstantString(exceptionIndexTable[i],
|
||||
Const.CONSTANT_Class).replace('/', '.');
|
||||
}
|
||||
return names;
|
||||
public void setExceptionIndexTable(final int[] exceptionIndexTable) {
|
||||
this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param exceptionIndexTable the list of exception indexes
|
||||
* Also redefines number_of_exceptions according to table length.
|
||||
*/
|
||||
public void setExceptionIndexTable( final int[] exceptionIndexTable ) {
|
||||
this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : new int[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation, i.e., a list of thrown exceptions.
|
||||
*/
|
||||
@@ -166,20 +176,4 @@ public final class ExceptionTable extends Attribute {
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final ExceptionTable c = (ExceptionTable) clone();
|
||||
if (exceptionIndexTable != null) {
|
||||
c.exceptionIndexTable = new int[exceptionIndexTable.length];
|
||||
System.arraycopy(exceptionIndexTable, 0, c.exceptionIndexTable, 0,
|
||||
exceptionIndexTable.length);
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,75 +30,111 @@ import com.sun.org.apache.bcel.internal.generic.Type;
|
||||
import com.sun.org.apache.bcel.internal.util.BCELComparator;
|
||||
|
||||
/**
|
||||
* This class represents the field info structure, i.e., the representation
|
||||
* for a variable in the class. See JVM specification for details.
|
||||
*
|
||||
* This class represents the field info structure, i.e., the representation for a variable in the class. See JVM
|
||||
* specification for details.
|
||||
*/
|
||||
public final class Field extends FieldOrMethod {
|
||||
|
||||
/**
|
||||
* Empty array constant.
|
||||
*
|
||||
* @since 6.6.0
|
||||
*/
|
||||
public static final Field[] EMPTY_ARRAY = {};
|
||||
|
||||
private static BCELComparator bcelComparator = new BCELComparator() {
|
||||
|
||||
@Override
|
||||
public boolean equals( final Object o1, final Object o2 ) {
|
||||
public boolean equals(final Object o1, final Object o2) {
|
||||
final Field THIS = (Field) o1;
|
||||
final Field THAT = (Field) o2;
|
||||
return Objects.equals(THIS.getName(), THAT.getName())
|
||||
&& Objects.equals(THIS.getSignature(), THAT.getSignature());
|
||||
return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode( final Object o ) {
|
||||
public int hashCode(final Object o) {
|
||||
final Field THIS = (Field) o;
|
||||
return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
static final Field[] EMPTY_FIELD_ARRAY = {};
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
* @return Comparison strategy object
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
*
|
||||
* @param file Input stream
|
||||
*/
|
||||
Field(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException {
|
||||
super(file, constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public Field(final Field c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
* @param file Input stream
|
||||
*/
|
||||
Field(final DataInput file, final ConstantPool constant_pool) throws IOException,
|
||||
ClassFormatException {
|
||||
super(file, constant_pool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param access_flags Access rights of field
|
||||
* @param name_index Points to field name in constant pool
|
||||
* @param signature_index Points to encoded signature
|
||||
* @param accessFlags Access rights of field
|
||||
* @param nameIndex Points to field name in constant pool
|
||||
* @param signatureIndex Points to encoded signature
|
||||
* @param attributes Collection of attributes
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public Field(final int access_flags, final int name_index, final int signature_index, final Attribute[] attributes,
|
||||
final ConstantPool constant_pool) {
|
||||
super(access_flags, name_index, signature_index, attributes, constant_pool);
|
||||
public Field(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
|
||||
super(accessFlags, nameIndex, signatureIndex, attributes, constantPool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitField(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this field
|
||||
*/
|
||||
public Field copy(final ConstantPool constantPool) {
|
||||
return (Field) copy_(constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value as defined by given BCELComparator strategy. By default two Field objects are said to be equal when
|
||||
* their names and signatures are equal.
|
||||
*
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return bcelComparator.equals(this, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return constant value associated with this field (may be null)
|
||||
@@ -112,10 +148,26 @@ public final class Field extends FieldOrMethod {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return type of field
|
||||
*/
|
||||
public Type getType() {
|
||||
return Type.getReturnType(getSignature());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string representation close to declaration format,
|
||||
* `public static final short MAX = 100', e.g..
|
||||
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR
|
||||
* signature.
|
||||
*
|
||||
* @see Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return bcelComparator.hashCode(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string representation close to declaration format, 'public static final short MAX = 100', e.g..
|
||||
*
|
||||
* @return String representation of field, including the signature.
|
||||
*/
|
||||
@@ -127,7 +179,7 @@ public final class Field extends FieldOrMethod {
|
||||
|
||||
// Get names from constant pool
|
||||
access = Utility.accessToString(super.getAccessFlags());
|
||||
access = access.isEmpty() ? "" : (access + " ");
|
||||
access = access.isEmpty() ? "" : access + " ";
|
||||
signature = Utility.signatureToString(getSignature());
|
||||
name = getName();
|
||||
final StringBuilder buf = new StringBuilder(64); // CHECKSTYLE IGNORE MagicNumber
|
||||
@@ -143,61 +195,4 @@ public final class Field extends FieldOrMethod {
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this field
|
||||
*/
|
||||
public Field copy( final ConstantPool _constant_pool ) {
|
||||
return (Field) copy_(_constant_pool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return type of field
|
||||
*/
|
||||
public Type getType() {
|
||||
return Type.getReturnType(getSignature());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator( final BCELComparator comparator ) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return value as defined by given BCELComparator strategy.
|
||||
* By default two Field objects are said to be equal when
|
||||
* their names and signatures are equal.
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals( final Object obj ) {
|
||||
return bcelComparator.equals(this, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return value as defined by given BCELComparator strategy.
|
||||
* By default return the hashcode of the field's name XOR signature.
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return bcelComparator.hashCode(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Abstract super class for fields and methods.
|
||||
@@ -32,89 +31,121 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
* @LastModified: Jan 2020
|
||||
*/
|
||||
public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node {
|
||||
private int name_index; // Points to field name in constant pool
|
||||
private int signature_index; // Points to encoded signature
|
||||
private Attribute[] attributes; // Collection of attributes
|
||||
private int attributes_count; // No. of attributes
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int name_index; // Points to field name in constant pool
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int signature_index; // Points to encoded signature
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected Attribute[] attributes; // Collection of attributes
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be removed (not needed)
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int attributes_count; // No. of attributes
|
||||
|
||||
// @since 6.0
|
||||
private AnnotationEntry[] annotationEntries; // annotations defined on the field or method
|
||||
|
||||
private ConstantPool constant_pool;
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected ConstantPool constant_pool;
|
||||
|
||||
private String signatureAttributeString = null;
|
||||
private boolean searchedForSignatureAttribute = false;
|
||||
private String signatureAttributeString;
|
||||
private boolean searchedForSignatureAttribute;
|
||||
|
||||
FieldOrMethod() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
*/
|
||||
protected FieldOrMethod(final FieldOrMethod c) {
|
||||
this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(),
|
||||
c.getAttributes(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
* @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected FieldOrMethod(final DataInputStream file, final ConstantPool constant_pool)
|
||||
throws IOException,
|
||||
ClassFormatException {
|
||||
this((DataInput) file, constant_pool);
|
||||
protected FieldOrMethod(final DataInput file, final ConstantPool constantPool) throws IOException {
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, constantPool);
|
||||
final int attributesCount = file.readUnsignedShort();
|
||||
attributes = new Attribute[attributesCount];
|
||||
for (int i = 0; i < attributesCount; i++) {
|
||||
attributes[i] = Attribute.readAttribute(file, constantPool);
|
||||
}
|
||||
this.attributes_count = attributesCount; // init deprecated field
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @deprecated (6.0) Use {@link #FieldOrMethod(java.io.DataInput, ConstantPool)} instead.
|
||||
*/
|
||||
protected FieldOrMethod(final DataInput file, final ConstantPool constant_pool)
|
||||
throws IOException, ClassFormatException {
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null,
|
||||
constant_pool);
|
||||
final int attributes_count = file.readUnsignedShort();
|
||||
attributes = new Attribute[attributes_count];
|
||||
for (int i = 0; i < attributes_count; i++) {
|
||||
attributes[i] = Attribute.readAttribute(file, constant_pool);
|
||||
}
|
||||
this.attributes_count = attributes_count; // init deprecated field
|
||||
@java.lang.Deprecated
|
||||
protected FieldOrMethod(final DataInputStream file, final ConstantPool constantPool) throws IOException {
|
||||
this((DataInput) file, constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
protected FieldOrMethod(final FieldOrMethod c) {
|
||||
this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c.getConstantPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param access_flags Access rights of method
|
||||
* @param name_index Points to field name in constant pool
|
||||
* @param signature_index Points to encoded signature
|
||||
* @param accessFlags Access rights of method
|
||||
* @param nameIndex Points to field name in constant pool
|
||||
* @param signatureIndex Points to encoded signature
|
||||
* @param attributes Collection of attributes
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
protected FieldOrMethod(final int access_flags, final int name_index, final int signature_index,
|
||||
final Attribute[] attributes, final ConstantPool constant_pool) {
|
||||
super(access_flags);
|
||||
this.name_index = name_index;
|
||||
this.signature_index = signature_index;
|
||||
this.constant_pool = constant_pool;
|
||||
protected FieldOrMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes,
|
||||
final ConstantPool constantPool) {
|
||||
super(accessFlags);
|
||||
this.name_index = nameIndex;
|
||||
this.signature_index = signatureIndex;
|
||||
this.constant_pool = constantPool;
|
||||
setAttributes(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this field
|
||||
*/
|
||||
protected FieldOrMethod copy_(final ConstantPool constantPool) {
|
||||
try {
|
||||
final FieldOrMethod c = (FieldOrMethod) clone();
|
||||
c.constant_pool = constantPool;
|
||||
c.attributes = new Attribute[attributes.length];
|
||||
c.attributes_count = attributes_count; // init deprecated field
|
||||
Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool));
|
||||
return c;
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump object to file stream on binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(super.getAccessFlags());
|
||||
@@ -128,115 +159,6 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Collection of object attributes.
|
||||
*/
|
||||
public final Attribute[] getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param attributes Collection of object attributes.
|
||||
*/
|
||||
public final void setAttributes( final Attribute[] attributes ) {
|
||||
this.attributes = attributes;
|
||||
this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Constant pool used by this object.
|
||||
*/
|
||||
public final ConstantPool getConstantPool() {
|
||||
return constant_pool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param constant_pool Constant pool to be used for this object.
|
||||
*/
|
||||
public final void setConstantPool( final ConstantPool constant_pool ) {
|
||||
this.constant_pool = constant_pool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of object's name.
|
||||
*/
|
||||
public final int getNameIndex() {
|
||||
return name_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool of object's name.
|
||||
*/
|
||||
public final void setNameIndex( final int name_index ) {
|
||||
this.name_index = name_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of field signature.
|
||||
*/
|
||||
public final int getSignatureIndex() {
|
||||
return signature_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param signature_index Index in constant pool of field signature.
|
||||
*/
|
||||
public final void setSignatureIndex( final int signature_index ) {
|
||||
this.signature_index = signature_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Name of object, i.e., method name or field name
|
||||
*/
|
||||
public final String getName() {
|
||||
ConstantUtf8 c;
|
||||
c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation of object's type signature (java style)
|
||||
*/
|
||||
public final String getSignature() {
|
||||
ConstantUtf8 c;
|
||||
c = (ConstantUtf8) constant_pool.getConstant(signature_index, Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this field
|
||||
*/
|
||||
protected FieldOrMethod copy_( final ConstantPool _constant_pool ) {
|
||||
FieldOrMethod c = null;
|
||||
|
||||
try {
|
||||
c = (FieldOrMethod)clone();
|
||||
} catch(final CloneNotSupportedException e) {
|
||||
// ignored, but will cause NPE ...
|
||||
}
|
||||
|
||||
c.constant_pool = constant_pool;
|
||||
c.attributes = new Attribute[attributes.length];
|
||||
c.attributes_count = attributes_count; // init deprecated field
|
||||
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
c.attributes[i] = attributes[i].copy(constant_pool);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Annotations on the field or method
|
||||
* @since 6.0
|
||||
@@ -250,26 +172,32 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
}
|
||||
|
||||
/**
|
||||
* Hunts for a signature attribute on the member and returns its contents.
|
||||
* So where the 'regular' signature may be (Ljava/util/Vector;)V the
|
||||
* signature attribute may in fact say
|
||||
* 'Ljava/lang/Vector<Ljava/lang/String>;' Coded for performance -
|
||||
* searches for the attribute only when requested - only searches for it
|
||||
* once.
|
||||
* @return Collection of object attributes.
|
||||
*/
|
||||
public final Attribute[] getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Constant pool used by this object.
|
||||
*/
|
||||
public final ConstantPool getConstantPool() {
|
||||
return constant_pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be
|
||||
* (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector<Ljava/lang/String>;' Coded for
|
||||
* performance - searches for the attribute only when requested - only searches for it once.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public final String getGenericSignature()
|
||||
{
|
||||
if (!searchedForSignatureAttribute)
|
||||
{
|
||||
public final String getGenericSignature() {
|
||||
if (!searchedForSignatureAttribute) {
|
||||
boolean found = false;
|
||||
for (int i = 0; !found && i < attributes.length; i++)
|
||||
{
|
||||
if (attributes[i] instanceof Signature)
|
||||
{
|
||||
signatureAttributeString = ((Signature) attributes[i])
|
||||
.getSignature();
|
||||
for (int i = 0; !found && i < attributes.length; i++) {
|
||||
if (attributes[i] instanceof Signature) {
|
||||
signatureAttributeString = ((Signature) attributes[i]).getSignature();
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
@@ -277,4 +205,61 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
}
|
||||
return signatureAttributeString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name of object, i.e., method name or field name
|
||||
*/
|
||||
public final String getName() {
|
||||
return constant_pool.getConstantUtf8(name_index).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of object's name.
|
||||
*/
|
||||
public final int getNameIndex() {
|
||||
return name_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation of object's type signature (java style)
|
||||
*/
|
||||
public final String getSignature() {
|
||||
return constant_pool.getConstantUtf8(signature_index).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of field signature.
|
||||
*/
|
||||
public final int getSignatureIndex() {
|
||||
return signature_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes Collection of object attributes.
|
||||
*/
|
||||
public final void setAttributes(final Attribute[] attributes) {
|
||||
this.attributes = attributes;
|
||||
this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
*/
|
||||
public final void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constant_pool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool of object's name.
|
||||
*/
|
||||
public final void setNameIndex(final int nameIndex) {
|
||||
this.name_index = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param signatureIndex Index in constant pool of field signature.
|
||||
*/
|
||||
public final void setSignatureIndex(final int signatureIndex) {
|
||||
this.signature_index = signatureIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,8 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents a inner class attribute, i.e., the class
|
||||
* indices of the inner and outer classes, the name and the attributes
|
||||
* of the inner class.
|
||||
* This class represents a inner class attribute, i.e., the class indices of the inner and outer classes, the name and
|
||||
* the attributes of the inner class.
|
||||
*
|
||||
* @see InnerClasses
|
||||
*/
|
||||
@@ -41,171 +40,49 @@ public final class InnerClass implements Cloneable, Node {
|
||||
private int innerNameIndex;
|
||||
private int innerAccessFlags;
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
InnerClass(final DataInput file) throws IOException {
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public InnerClass(final InnerClass c) {
|
||||
this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c
|
||||
.getInnerAccessFlags());
|
||||
this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c.getInnerAccessFlags());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
*/
|
||||
InnerClass(final DataInput file) throws IOException {
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
|
||||
.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param innerClassIndex Class index in constant pool of inner class
|
||||
* @param outerClassIndex Class index in constant pool of outer class
|
||||
* @param innerNameIndex Name index in constant pool of inner class
|
||||
* @param innerNameIndex Name index in constant pool of inner class
|
||||
* @param innerAccessFlags Access flags of inner class
|
||||
*/
|
||||
public InnerClass(final int innerClassIndex, final int outerClassIndex, final int innerNameIndex,
|
||||
final int innerAccessFlags) {
|
||||
public InnerClass(final int innerClassIndex, final int outerClassIndex, final int innerNameIndex, final int innerAccessFlags) {
|
||||
this.innerClassIndex = innerClassIndex;
|
||||
this.outerClassIndex = outerClassIndex;
|
||||
this.innerNameIndex = innerNameIndex;
|
||||
this.innerAccessFlags = innerAccessFlags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitInnerClass(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump inner class attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
file.writeShort(innerClassIndex);
|
||||
file.writeShort(outerClassIndex);
|
||||
file.writeShort(innerNameIndex);
|
||||
file.writeShort(innerAccessFlags);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return access flags of inner class.
|
||||
*/
|
||||
public int getInnerAccessFlags() {
|
||||
return innerAccessFlags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return class index of inner class.
|
||||
*/
|
||||
public int getInnerClassIndex() {
|
||||
return innerClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return name index of inner class.
|
||||
*/
|
||||
public int getInnerNameIndex() {
|
||||
return innerNameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return class index of outer class.
|
||||
*/
|
||||
public int getOuterClassIndex() {
|
||||
return outerClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param innerAccessFlags access flags for this inner class
|
||||
*/
|
||||
public void setInnerAccessFlags( final int innerAccessFlags ) {
|
||||
this.innerAccessFlags = innerAccessFlags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param innerClassIndex index into the constant pool for this class
|
||||
*/
|
||||
public void setInnerClassIndex( final int innerClassIndex ) {
|
||||
this.innerClassIndex = innerClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param innerNameIndex index into the constant pool for this class's name
|
||||
*/
|
||||
public void setInnerNameIndex( final int innerNameIndex ) { // TODO unused
|
||||
this.innerNameIndex = innerNameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param outerClassIndex index into the constant pool for the owning class
|
||||
*/
|
||||
public void setOuterClassIndex( final int outerClassIndex ) { // TODO unused
|
||||
this.outerClassIndex = outerClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InnerClass(" + innerClassIndex + ", " + outerClassIndex + ", "
|
||||
+ innerNameIndex + ", " + innerAccessFlags + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString( final ConstantPool constantPool ) {
|
||||
String outer_class_name;
|
||||
String inner_name;
|
||||
String inner_class_name = constantPool.getConstantString(innerClassIndex,
|
||||
Const.CONSTANT_Class);
|
||||
inner_class_name = Utility.compactClassName(inner_class_name, false);
|
||||
if (outerClassIndex != 0) {
|
||||
outer_class_name = constantPool.getConstantString(outerClassIndex,
|
||||
Const.CONSTANT_Class);
|
||||
outer_class_name = " of class " + Utility.compactClassName(outer_class_name, false);
|
||||
} else {
|
||||
outer_class_name = "";
|
||||
}
|
||||
if (innerNameIndex != 0) {
|
||||
inner_name = ((ConstantUtf8) constantPool.getConstant(innerNameIndex,
|
||||
Const.CONSTANT_Utf8)).getBytes();
|
||||
} else {
|
||||
inner_name = "(anonymous)";
|
||||
}
|
||||
String access = Utility.accessToString(innerAccessFlags, true);
|
||||
access = access.isEmpty() ? "" : (access + " ");
|
||||
return " " + access + inner_name + "=class " + inner_class_name + outer_class_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@@ -217,4 +94,105 @@ public final class InnerClass implements Cloneable, Node {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump inner class attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(innerClassIndex);
|
||||
file.writeShort(outerClassIndex);
|
||||
file.writeShort(innerNameIndex);
|
||||
file.writeShort(innerAccessFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return access flags of inner class.
|
||||
*/
|
||||
public int getInnerAccessFlags() {
|
||||
return innerAccessFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class index of inner class.
|
||||
*/
|
||||
public int getInnerClassIndex() {
|
||||
return innerClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return name index of inner class.
|
||||
*/
|
||||
public int getInnerNameIndex() {
|
||||
return innerNameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class index of outer class.
|
||||
*/
|
||||
public int getOuterClassIndex() {
|
||||
return outerClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerAccessFlags access flags for this inner class
|
||||
*/
|
||||
public void setInnerAccessFlags(final int innerAccessFlags) {
|
||||
this.innerAccessFlags = innerAccessFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerClassIndex index into the constant pool for this class
|
||||
*/
|
||||
public void setInnerClassIndex(final int innerClassIndex) {
|
||||
this.innerClassIndex = innerClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerNameIndex index into the constant pool for this class's name
|
||||
*/
|
||||
public void setInnerNameIndex(final int innerNameIndex) { // TODO unused
|
||||
this.innerNameIndex = innerNameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param outerClassIndex index into the constant pool for the owning class
|
||||
*/
|
||||
public void setOuterClassIndex(final int outerClassIndex) { // TODO unused
|
||||
this.outerClassIndex = outerClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InnerClass(" + innerClassIndex + ", " + outerClassIndex + ", " + innerNameIndex + ", " + innerAccessFlags + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString(final ConstantPool constantPool) {
|
||||
String outerClassName;
|
||||
String innerName;
|
||||
String innerClassName = constantPool.getConstantString(innerClassIndex, Const.CONSTANT_Class);
|
||||
innerClassName = Utility.compactClassName(innerClassName, false);
|
||||
if (outerClassIndex != 0) {
|
||||
outerClassName = constantPool.getConstantString(outerClassIndex, Const.CONSTANT_Class);
|
||||
outerClassName = " of class " + Utility.compactClassName(outerClassName, false);
|
||||
} else {
|
||||
outerClassName = "";
|
||||
}
|
||||
if (innerNameIndex != 0) {
|
||||
innerName = constantPool.getConstantUtf8(innerNameIndex).getBytes();
|
||||
} else {
|
||||
innerName = "(anonymous)";
|
||||
}
|
||||
String access = Utility.accessToString(innerAccessFlags, true);
|
||||
access = access.isEmpty() ? "" : access + " ";
|
||||
return " " + access + innerName + "=class " + innerClassName + outerClassName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,93 +24,107 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and denotes that this class
|
||||
* is an Inner class of another.
|
||||
* to the source file of this class.
|
||||
* It is instantiated from the <em>Attribute.readAttribute()</em> method.
|
||||
* This class is derived from <em>Attribute</em> and denotes that this class is an Inner class of another. to the source
|
||||
* file of this class. It is instantiated from the <em>Attribute.readAttribute()</em> method.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class InnerClasses extends Attribute {
|
||||
public final class InnerClasses extends Attribute implements Iterable<InnerClass> {
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
private static final InnerClass[] EMPTY_INNER_CLASSE_ARRAY = {};
|
||||
|
||||
private InnerClass[] innerClasses;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public InnerClasses(final InnerClasses c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getInnerClasses(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param innerClasses array of inner classes attributes
|
||||
* @param constant_pool Array of constants
|
||||
*/
|
||||
public InnerClasses(final int name_index, final int length, final InnerClass[] innerClasses,
|
||||
final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_INNER_CLASSES, name_index, length, constant_pool);
|
||||
this.innerClasses = innerClasses != null ? innerClasses : new InnerClass[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
InnerClasses(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, (InnerClass[]) null, constant_pool);
|
||||
final int number_of_classes = input.readUnsignedShort();
|
||||
innerClasses = new InnerClass[number_of_classes];
|
||||
for (int i = 0; i < number_of_classes; i++) {
|
||||
InnerClasses(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (InnerClass[]) null, constantPool);
|
||||
final int classCount = input.readUnsignedShort();
|
||||
innerClasses = new InnerClass[classCount];
|
||||
for (int i = 0; i < classCount; i++) {
|
||||
innerClasses[i] = new InnerClass(input);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param innerClasses array of inner classes attributes
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public InnerClasses(final int nameIndex, final int length, final InnerClass[] innerClasses, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_INNER_CLASSES, nameIndex, length, constantPool);
|
||||
this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY;
|
||||
Args.requireU2(this.innerClasses.length, "innerClasses.length");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitInnerClasses(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
// TODO this could be recoded to use a lower level constructor after creating a copy of the inner classes
|
||||
final InnerClasses c = (InnerClasses) clone();
|
||||
c.innerClasses = new InnerClass[innerClasses.length];
|
||||
Arrays.setAll(c.innerClasses, i -> innerClasses[i].copy());
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump source file attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(innerClasses.length);
|
||||
for (final InnerClass inner_class : innerClasses) {
|
||||
inner_class.dump(file);
|
||||
for (final InnerClass innerClass : innerClasses) {
|
||||
innerClass.dump(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array of inner class "records"
|
||||
*/
|
||||
@@ -118,15 +132,18 @@ public final class InnerClasses extends Attribute {
|
||||
return innerClasses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<InnerClass> iterator() {
|
||||
return Stream.of(innerClasses).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerClasses the array of inner classes
|
||||
*/
|
||||
public void setInnerClasses( final InnerClass[] innerClasses ) {
|
||||
this.innerClasses = innerClasses != null ? innerClasses : new InnerClass[0];
|
||||
public void setInnerClasses(final InnerClass[] innerClasses) {
|
||||
this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@@ -136,25 +153,9 @@ public final class InnerClasses extends Attribute {
|
||||
buf.append("InnerClasses(");
|
||||
buf.append(innerClasses.length);
|
||||
buf.append("):\n");
|
||||
for (final InnerClass inner_class : innerClasses) {
|
||||
buf.append(inner_class.toString(super.getConstantPool())).append("\n");
|
||||
for (final InnerClass innerClass : innerClasses) {
|
||||
buf.append(innerClass.toString(super.getConstantPool())).append("\n");
|
||||
}
|
||||
return buf.substring(0, buf.length()-1); // remove the last newline
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
// TODO this could be recoded to use a lower level constructor after creating a copy of the inner classes
|
||||
final InnerClasses c = (InnerClasses) clone();
|
||||
c.innerClasses = new InnerClass[innerClasses.length];
|
||||
for (int i = 0; i < innerClasses.length; i++) {
|
||||
c.innerClasses[i] = innerClasses[i].copy();
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
return buf.substring(0, buf.length() - 1); // remove the last newline
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,30 +25,23 @@ import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class represents a (PC offset, line number) pair, i.e., a line number in
|
||||
* the source that corresponds to a relative address in the byte code. This
|
||||
* is used for debugging purposes.
|
||||
* This class represents a (PC offset, line number) pair, i.e., a line number in the source that corresponds to a
|
||||
* relative address in the byte code. This is used for debugging purposes.
|
||||
*
|
||||
* @see LineNumberTable
|
||||
* @see LineNumberTable
|
||||
*/
|
||||
public final class LineNumber implements Cloneable, Node {
|
||||
|
||||
static final LineNumber[] EMPTY_ARRAY = {};
|
||||
|
||||
/** Program Counter (PC) corresponds to line */
|
||||
private short startPc;
|
||||
private int startPc;
|
||||
|
||||
/** number in source file */
|
||||
private short lineNumber;
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c the object to copy
|
||||
*/
|
||||
public LineNumber(final LineNumber c) {
|
||||
this(c.getStartPC(), c.getLineNumber());
|
||||
}
|
||||
|
||||
private int lineNumber;
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
@@ -60,83 +53,35 @@ public final class LineNumber implements Cloneable, Node {
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param startPc Program Counter (PC) corresponds to
|
||||
* @param lineNumber line number in source file
|
||||
*/
|
||||
public LineNumber(final int startPc, final int lineNumber) {
|
||||
this.startPc = (short) startPc;
|
||||
this.lineNumber = (short)lineNumber;
|
||||
this.startPc = Args.requireU2(startPc, "startPc");
|
||||
this.lineNumber = Args.requireU2(lineNumber, "lineNumber");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object.
|
||||
*
|
||||
* @param c the object to copy
|
||||
*/
|
||||
public LineNumber(final LineNumber c) {
|
||||
this(c.getStartPC(), c.getLineNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitLineNumber(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump line number/pc pair to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
file.writeShort(startPc);
|
||||
file.writeShort(lineNumber);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Corresponding source line
|
||||
*/
|
||||
public int getLineNumber() {
|
||||
return 0xffff & lineNumber;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return PC in code
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return 0xffff & startPc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param lineNumber the source line number
|
||||
*/
|
||||
public void setLineNumber( final int lineNumber ) {
|
||||
this.lineNumber = (short) lineNumber;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param startPc the pc for this line number
|
||||
*/
|
||||
public void setStartPC( final int startPc ) {
|
||||
this.startPc = (short) startPc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LineNumber(" + startPc + ", " + lineNumber + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@@ -148,4 +93,51 @@ public final class LineNumber implements Cloneable, Node {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump line number/pc pair to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(startPc);
|
||||
file.writeShort(lineNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Corresponding source line
|
||||
*/
|
||||
public int getLineNumber() {
|
||||
return lineNumber & 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PC in code
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return startPc & 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lineNumber the source line number
|
||||
*/
|
||||
public void setLineNumber(final int lineNumber) {
|
||||
this.lineNumber = (short) lineNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startPc the pc for this line number
|
||||
*/
|
||||
public void setStartPC(final int startPc) {
|
||||
this.startPc = (short) startPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LineNumber(" + getStartPC() + ", " + getLineNumber() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,78 +19,96 @@
|
||||
*/
|
||||
package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
import jdk.xml.internal.SecuritySupport;
|
||||
|
||||
/**
|
||||
* This class represents a table of line numbers for debugging
|
||||
* purposes. This attribute is used by the <em>Code</em> attribute. It
|
||||
* contains pairs of PCs and line numbers.
|
||||
* This class represents a table of line numbers for debugging purposes. This attribute is used by the <em>Code</em>
|
||||
* attribute. It contains pairs of PCs and line numbers.
|
||||
*
|
||||
* @see Code
|
||||
* @see Code
|
||||
* @see LineNumber
|
||||
* @LastModified: May 2021
|
||||
*/
|
||||
public final class LineNumberTable extends Attribute {
|
||||
public final class LineNumberTable extends Attribute implements Iterable<LineNumber> {
|
||||
|
||||
private static final int MAX_LINE_LENGTH = 72;
|
||||
private LineNumber[] lineNumberTable; // Table of line/numbers pairs
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index of name
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O Exception occurs in readUnsignedShort
|
||||
*/
|
||||
LineNumberTable(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (LineNumber[]) null, constantPool);
|
||||
final int lineNumberTableLength = input.readUnsignedShort();
|
||||
lineNumberTable = new LineNumber[lineNumberTableLength];
|
||||
for (int i = 0; i < lineNumberTableLength; i++) {
|
||||
lineNumberTable[i] = new LineNumber(input);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
* @param nameIndex Index of name
|
||||
*
|
||||
* @param length Content length in bytes
|
||||
*
|
||||
* @param lineNumberTable Table of line/numbers pairs
|
||||
*
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public LineNumberTable(final int nameIndex, final int length, final LineNumber[] lineNumberTable, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_LINE_NUMBER_TABLE, nameIndex, length, constantPool);
|
||||
this.lineNumberTable = lineNumberTable != null ? lineNumberTable : LineNumber.EMPTY_ARRAY;
|
||||
Args.requireU2(this.lineNumberTable.length, "lineNumberTable.length");
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*/
|
||||
public LineNumberTable(final LineNumberTable c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @param name_index Index of name
|
||||
* @param length Content length in bytes
|
||||
* @param lineNumberTable Table of line/numbers pairs
|
||||
* @param constant_pool Array of constants
|
||||
*/
|
||||
public LineNumberTable(final int name_index, final int length, final LineNumber[] line_number_table,
|
||||
final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_LINE_NUMBER_TABLE, name_index, length, constant_pool);
|
||||
this.lineNumberTable = line_number_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* @param name_index Index of name
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException if an I/O Exception occurs in readUnsignedShort
|
||||
*/
|
||||
LineNumberTable(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, (LineNumber[]) null, constant_pool);
|
||||
final int line_number_table_length = input.readUnsignedShort();
|
||||
lineNumberTable = new LineNumber[line_number_table_length];
|
||||
for (int i = 0; i < line_number_table_length; i++) {
|
||||
lineNumberTable[i] = new LineNumber(input);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitLineNumberTable(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
// TODO could use the lower level constructor and thereby allow
|
||||
// lineNumberTable to be made final
|
||||
final LineNumberTable c = (LineNumberTable) clone();
|
||||
c.lineNumberTable = new LineNumber[lineNumberTable.length];
|
||||
Arrays.setAll(c.lineNumberTable, i -> lineNumberTable[i].copy());
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump line number table attribute to file stream in binary format.
|
||||
*
|
||||
@@ -98,7 +116,7 @@ public final class LineNumberTable extends Attribute {
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(lineNumberTable.length);
|
||||
for (final LineNumber lineNumber : lineNumberTable) {
|
||||
@@ -113,10 +131,65 @@ public final class LineNumberTable extends Attribute {
|
||||
return lineNumberTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map byte code positions to source code lines.
|
||||
*
|
||||
* @param pos byte code offset
|
||||
* @return corresponding line in source code
|
||||
*/
|
||||
public int getSourceLine(final int pos) {
|
||||
int l = 0;
|
||||
int r = lineNumberTable.length - 1;
|
||||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
int minIndex = -1;
|
||||
int min = -1;
|
||||
/*
|
||||
* Do a binary search since the array is ordered.
|
||||
*/
|
||||
do {
|
||||
final int i = l + r >>> 1;
|
||||
final int j = lineNumberTable[i].getStartPC();
|
||||
if (j == pos) {
|
||||
return lineNumberTable[i].getLineNumber();
|
||||
}
|
||||
if (pos < j) {
|
||||
r = i - 1;
|
||||
} else {
|
||||
l = i + 1;
|
||||
}
|
||||
/*
|
||||
* If exact match can't be found (which is the most common case) return the line number that corresponds to the greatest
|
||||
* index less than pos.
|
||||
*/
|
||||
if (j < pos && j > min) {
|
||||
min = j;
|
||||
minIndex = i;
|
||||
}
|
||||
} while (l <= r);
|
||||
/*
|
||||
* It's possible that we did not find any valid entry for the bytecode offset we were looking for.
|
||||
*/
|
||||
if (minIndex < 0) {
|
||||
return -1;
|
||||
}
|
||||
return lineNumberTable[minIndex].getLineNumber();
|
||||
}
|
||||
|
||||
public int getTableLength() {
|
||||
return lineNumberTable == null ? 0 : lineNumberTable.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<LineNumber> iterator() {
|
||||
return Stream.of(lineNumberTable).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lineNumberTable the line number entries for this table
|
||||
*/
|
||||
public void setLineNumberTable( final LineNumber[] lineNumberTable ) {
|
||||
public void setLineNumberTable(final LineNumber[] lineNumberTable) {
|
||||
this.lineNumberTable = lineNumberTable;
|
||||
}
|
||||
|
||||
@@ -127,13 +200,12 @@ public final class LineNumberTable extends Attribute {
|
||||
public String toString() {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final StringBuilder line = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < lineNumberTable.length; i++) {
|
||||
line.append(lineNumberTable[i].toString());
|
||||
if (i < lineNumberTable.length - 1) {
|
||||
line.append(", ");
|
||||
}
|
||||
if ((line.length() > MAX_LINE_LENGTH) && (i < lineNumberTable.length - 1)) {
|
||||
if (line.length() > MAX_LINE_LENGTH && i < lineNumberTable.length - 1) {
|
||||
line.append(SecuritySupport.NEWLINE);
|
||||
buf.append(line);
|
||||
line.setLength(0);
|
||||
@@ -142,69 +214,4 @@ public final class LineNumberTable extends Attribute {
|
||||
buf.append(line);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Map byte code positions to source code lines.
|
||||
*
|
||||
* @param pos byte code offset
|
||||
* @return corresponding line in source code
|
||||
*/
|
||||
public int getSourceLine( final int pos ) {
|
||||
int l = 0;
|
||||
int r = lineNumberTable.length - 1;
|
||||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
int min_index = -1;
|
||||
int min = -1;
|
||||
/* Do a binary search since the array is ordered.
|
||||
*/
|
||||
do {
|
||||
final int i = (l + r) >>> 1;
|
||||
final int j = lineNumberTable[i].getStartPC();
|
||||
if (j == pos) {
|
||||
return lineNumberTable[i].getLineNumber();
|
||||
} else if (pos < j) {
|
||||
r = i - 1;
|
||||
} else {
|
||||
l = i + 1;
|
||||
}
|
||||
/* If exact match can't be found (which is the most common case)
|
||||
* return the line number that corresponds to the greatest index less
|
||||
* than pos.
|
||||
*/
|
||||
if (j < pos && j > min) {
|
||||
min = j;
|
||||
min_index = i;
|
||||
}
|
||||
} while (l <= r);
|
||||
/* It's possible that we did not find any valid entry for the bytecode
|
||||
* offset we were looking for.
|
||||
*/
|
||||
if (min_index < 0) {
|
||||
return -1;
|
||||
}
|
||||
return lineNumberTable[min_index].getLineNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
// TODO could use the lower level constructor and thereby allow
|
||||
// lineNumberTable to be made final
|
||||
final LineNumberTable c = (LineNumberTable) clone();
|
||||
c.lineNumberTable = new LineNumber[lineNumberTable.length];
|
||||
for (int i = 0; i < lineNumberTable.length; i++) {
|
||||
c.lineNumberTable[i] = lineNumberTable[i].copy();
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
public int getTableLength() {
|
||||
return lineNumberTable == null ? 0 : lineNumberTable.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -24,119 +24,129 @@ import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class represents a local variable within a method. It contains its
|
||||
* scope, name, signature and index on the method's frame. It is used both
|
||||
* to represent an element of the LocalVariableTable as well as an element
|
||||
* of the LocalVariableTypeTable. The nomenclature used here may be a bit confusing;
|
||||
* while the two items have the same layout in a class file, a LocalVariableTable
|
||||
* attribute contains a descriptor_index, not a signatureIndex. The
|
||||
* This class represents a local variable within a method. It contains its scope, name, signature and index on the
|
||||
* method's frame. It is used both to represent an element of the LocalVariableTable as well as an element of the
|
||||
* LocalVariableTypeTable. The nomenclature used here may be a bit confusing; while the two items have the same layout
|
||||
* in a class file, a LocalVariableTable attribute contains a descriptor_index, not a signatureIndex. The
|
||||
* LocalVariableTypeTable attribute does have a signatureIndex.
|
||||
*
|
||||
* @see com.sun.org.apache.bcel.internal.classfile.Utility for more details on the difference.
|
||||
*
|
||||
* @see LocalVariableTable
|
||||
* @see LocalVariableTypeTable
|
||||
* @LastModified: May 2021
|
||||
* @see LocalVariableTable
|
||||
* @see LocalVariableTypeTable
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public final class LocalVariable implements Cloneable, Node {
|
||||
|
||||
private int startPc; // Range in which the variable is valid
|
||||
private int length;
|
||||
private int nameIndex; // Index in constant pool of variable name
|
||||
// Technically, a decscriptor_index for a local variable table entry
|
||||
// and a signatureIndex for a local variable type table entry.
|
||||
private int signatureIndex; // Index of variable signature
|
||||
private int index; /* Variable is index'th local variable on
|
||||
* this method's frame.
|
||||
*/
|
||||
private ConstantPool constantPool;
|
||||
private int origIndex; // never changes; used to match up with LocalVariableTypeTable entries
|
||||
static final LocalVariable[] EMPTY_ARRAY = {};
|
||||
|
||||
/** Range in which the variable is valid. */
|
||||
private int startPc;
|
||||
|
||||
private int length;
|
||||
|
||||
/** Index in constant pool of variable name. */
|
||||
private int nameIndex;
|
||||
|
||||
/**
|
||||
* Initializes from another LocalVariable. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
* Technically, a decscriptor_index for a local variable table entry and a signatureIndex for a local variable type table entry. Index of variable signature
|
||||
*/
|
||||
private int signatureIndex;
|
||||
|
||||
/*
|
||||
* Variable is index'th local variable on this method's frame.
|
||||
*/
|
||||
private int index;
|
||||
|
||||
private ConstantPool constantPool;
|
||||
|
||||
/** Never changes; used to match up with LocalVariableTypeTable entries. */
|
||||
private final int origIndex;
|
||||
|
||||
/**
|
||||
* Constructs object from file stream.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
LocalVariable(final DataInput file, final ConstantPool constantPool) throws IOException {
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startPc Range in which the variable
|
||||
* @param length ... is valid
|
||||
* @param nameIndex Index in constant pool of variable name
|
||||
* @param signatureIndex Index of variable's signature
|
||||
* @param index Variable is 'index'th local variable on the method's frame
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool) {
|
||||
this(startPc, length, nameIndex, signatureIndex, index, constantPool, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startPc Range in which the variable
|
||||
* @param length ... is valid
|
||||
* @param nameIndex Index in constant pool of variable name
|
||||
* @param signatureIndex Index of variable's signature
|
||||
* @param index Variable is 'index'th local variable on the method's frame
|
||||
* @param constantPool Array of constants
|
||||
* @param origIndex Variable is 'index'th local variable on the method's frame prior to any changes
|
||||
*/
|
||||
public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool,
|
||||
final int origIndex) {
|
||||
this.startPc = Args.requireU2(startPc, "startPc");
|
||||
this.length = Args.requireU2(length, "length");
|
||||
this.nameIndex = Args.requireU2(nameIndex, "nameIndex");
|
||||
this.signatureIndex = Args.requireU2(signatureIndex, "signatureIndex");
|
||||
this.index = Args.requireU2(index, "index");
|
||||
this.origIndex = Args.requireU2(origIndex, "origIndex");
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes from another LocalVariable. Note that both objects use the same references (shallow copy). Use copy() for
|
||||
* a physical copy.
|
||||
*
|
||||
* @param localVariable Another LocalVariable.
|
||||
*/
|
||||
public LocalVariable(final LocalVariable localVariable) {
|
||||
this(localVariable.getStartPC(), localVariable.getLength(), localVariable.getNameIndex(),
|
||||
localVariable.getSignatureIndex(), localVariable.getIndex(), localVariable.getConstantPool());
|
||||
this.origIndex = localVariable.getOrigIndex();
|
||||
this(localVariable.getStartPC(), localVariable.getLength(), localVariable.getNameIndex(), localVariable.getSignatureIndex(), localVariable.getIndex(),
|
||||
localVariable.getConstantPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs object from file stream.
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
*/
|
||||
LocalVariable(final DataInput file, final ConstantPool constant_pool) throws IOException {
|
||||
this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
|
||||
.readUnsignedShort(), file.readUnsignedShort(), constant_pool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param startPc Range in which the variable
|
||||
* @param length ... is valid
|
||||
* @param nameIndex Index in constant pool of variable name
|
||||
* @param signatureIndex Index of variable's signature
|
||||
* @param index Variable is `index'th local variable on the method's frame
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index,
|
||||
final ConstantPool constantPool) {
|
||||
this.startPc = startPc;
|
||||
this.length = length;
|
||||
this.nameIndex = nameIndex;
|
||||
this.signatureIndex = signatureIndex;
|
||||
this.index = index;
|
||||
this.constantPool = constantPool;
|
||||
this.origIndex = index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param startPc Range in which the variable
|
||||
* @param length ... is valid
|
||||
* @param nameIndex Index in constant pool of variable name
|
||||
* @param signatureIndex Index of variable's signature
|
||||
* @param index Variable is `index'th local variable on the method's frame
|
||||
* @param constantPool Array of constants
|
||||
* @param origIndex Variable is `index'th local variable on the method's frame prior to any changes
|
||||
*/
|
||||
public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index,
|
||||
final ConstantPool constantPool, final int origIndex) {
|
||||
this.startPc = startPc;
|
||||
this.length = length;
|
||||
this.nameIndex = nameIndex;
|
||||
this.signatureIndex = signatureIndex;
|
||||
this.index = index;
|
||||
this.constantPool = constantPool;
|
||||
this.origIndex = origIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitLocalVariable(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
public LocalVariable copy() {
|
||||
try {
|
||||
return (LocalVariable) clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
// TODO should this throw?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps local variable to file stream in binary format.
|
||||
*
|
||||
* @param dataOutputStream Output file stream
|
||||
* @exception IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @see java.io.FilterOutputStream#out
|
||||
*/
|
||||
public void dump(final DataOutputStream dataOutputStream) throws IOException {
|
||||
@@ -154,6 +164,12 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index of register where variable is stored
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Variable is valid within getStartPC() .. getStartPC()+getLength()
|
||||
@@ -162,17 +178,13 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Variable name.
|
||||
*/
|
||||
public String getName() {
|
||||
ConstantUtf8 c;
|
||||
c = (ConstantUtf8) constantPool.getConstant(nameIndex, Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
return constantPool.getConstantUtf8(nameIndex).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of variable name.
|
||||
*/
|
||||
@@ -180,17 +192,20 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index of register where variable was originally stored
|
||||
*/
|
||||
public int getOrigIndex() {
|
||||
return origIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Signature.
|
||||
*/
|
||||
public String getSignature() {
|
||||
ConstantUtf8 c;
|
||||
c = (ConstantUtf8) constantPool.getConstant(signatureIndex, Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
return constantPool.getConstantUtf8(signatureIndex).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of variable signature.
|
||||
*/
|
||||
@@ -198,23 +213,6 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return signatureIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return index of register where variable is stored
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return index of register where variable was originally stored
|
||||
*/
|
||||
public int getOrigIndex() {
|
||||
return origIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Start of range where the variable is valid
|
||||
*/
|
||||
@@ -222,67 +220,48 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return startPc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Helper method shared with LocalVariableTypeTable
|
||||
*/
|
||||
String toStringShared( final boolean typeTable ) {
|
||||
final String name = getName();
|
||||
final String signature = Utility.signatureToString(getSignature(), false);
|
||||
final String label = "LocalVariable" + (typeTable ? "Types" : "" );
|
||||
return label + "(startPc = " + startPc + ", length = " + length + ", index = "
|
||||
+ index + ":" + signature + " " + name + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
*/
|
||||
public void setConstantPool( final ConstantPool constantPool ) {
|
||||
public void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param length the length of this local variable
|
||||
*/
|
||||
public void setLength( final int length ) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex the index into the constant pool for the name of this variable
|
||||
*/
|
||||
public void setNameIndex( final int nameIndex ) { // TODO unused
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param signatureIndex the index into the constant pool for the signature of this variable
|
||||
*/
|
||||
public void setSignatureIndex( final int signatureIndex ) { // TODO unused
|
||||
this.signatureIndex = signatureIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param index the index in the local variable table of this variable
|
||||
*/
|
||||
public void setIndex( final int index ) { // TODO unused
|
||||
public void setIndex(final int index) { // TODO unused
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length the length of this local variable
|
||||
*/
|
||||
public void setLength(final int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex the index into the constant pool for the name of this variable
|
||||
*/
|
||||
public void setNameIndex(final int nameIndex) { // TODO unused
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param signatureIndex the index into the constant pool for the signature of this variable
|
||||
*/
|
||||
public void setSignatureIndex(final int signatureIndex) { // TODO unused
|
||||
this.signatureIndex = signatureIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startPc Specify range where the local variable is valid.
|
||||
*/
|
||||
public void setStartPC( final int startPc ) { // TODO unused
|
||||
public void setStartPC(final int startPc) { // TODO unused
|
||||
this.startPc = startPc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string representation.
|
||||
*/
|
||||
@@ -291,16 +270,13 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return toStringShared(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
/*
|
||||
* Helper method shared with LocalVariableTypeTable
|
||||
*/
|
||||
public LocalVariable copy() {
|
||||
try {
|
||||
return (LocalVariable) clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
// TODO should this throw?
|
||||
}
|
||||
return null;
|
||||
String toStringShared(final boolean typeTable) {
|
||||
final String name = getName();
|
||||
final String signature = Utility.signatureToString(getSignature(), false);
|
||||
final String label = "LocalVariable" + (typeTable ? "Types" : "");
|
||||
return label + "(startPc = " + startPc + ", length = " + length + ", index = " + index + ":" + signature + " " + name + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,83 +24,95 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class represents colection of local variables in a
|
||||
* method. This attribute is contained in the <em>Code</em> attribute.
|
||||
* This class represents colection of local variables in a method. This attribute is contained in the <em>Code</em>
|
||||
* attribute.
|
||||
*
|
||||
* @see Code
|
||||
* @see Code
|
||||
* @see LocalVariable
|
||||
*/
|
||||
public class LocalVariableTable extends Attribute {
|
||||
public class LocalVariableTable extends Attribute implements Iterable<LocalVariable> {
|
||||
|
||||
private LocalVariable[] localVariableTable; // variables
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
LocalVariableTable(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (LocalVariable[]) null, constantPool);
|
||||
final int localVariableTableLength = input.readUnsignedShort();
|
||||
localVariableTable = new LocalVariable[localVariableTableLength];
|
||||
for (int i = 0; i < localVariableTableLength; i++) {
|
||||
localVariableTable[i] = new LocalVariable(input, constantPool);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
* @param nameIndex Index in constant pool to 'LocalVariableTable'
|
||||
* @param length Content length in bytes
|
||||
* @param localVariableTable Table of local variables
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public LocalVariableTable(final int nameIndex, final int length, final LocalVariable[] localVariableTable, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_LOCAL_VARIABLE_TABLE, nameIndex, length, constantPool);
|
||||
this.localVariableTable = localVariableTable != null ? localVariableTable : LocalVariable.EMPTY_ARRAY;
|
||||
Args.requireU2(this.localVariableTable.length, "localVariableTable.length");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public LocalVariableTable(final LocalVariableTable c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getLocalVariableTable(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool to `LocalVariableTable'
|
||||
* @param length Content length in bytes
|
||||
* @param localVariableTable Table of local variables
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public LocalVariableTable(final int nameIndex, final int length, final LocalVariable[] localVariableTable,
|
||||
final ConstantPool constantPool) {
|
||||
super(Const.ATTR_LOCAL_VARIABLE_TABLE, nameIndex, length, constantPool);
|
||||
this.localVariableTable = localVariableTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* @param name_index Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
*/
|
||||
LocalVariableTable(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, (LocalVariable[]) null, constant_pool);
|
||||
final int local_variable_table_length = input.readUnsignedShort();
|
||||
localVariableTable = new LocalVariable[local_variable_table_length];
|
||||
for (int i = 0; i < local_variable_table_length; i++) {
|
||||
localVariableTable[i] = new LocalVariable(input, constant_pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitLocalVariableTable(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final LocalVariableTable c = (LocalVariableTable) clone();
|
||||
c.localVariableTable = new LocalVariable[localVariableTable.length];
|
||||
Arrays.setAll(c.localVariableTable, i -> localVariableTable[i].copy());
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump local variable table attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public final void dump( final DataOutputStream file ) throws IOException {
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(localVariableTable.length);
|
||||
for (final LocalVariable variable : localVariableTable) {
|
||||
@@ -108,26 +120,17 @@ public class LocalVariableTable extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Array of local variables of method.
|
||||
*/
|
||||
public final LocalVariable[] getLocalVariableTable() {
|
||||
return localVariableTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index the variable slot
|
||||
*
|
||||
* @return the first LocalVariable that matches the slot or null if not found
|
||||
*
|
||||
* @deprecated since 5.2 because multiple variables can share the
|
||||
* same slot, use getLocalVariable(int index, int pc) instead.
|
||||
* @deprecated since 5.2 because multiple variables can share the same slot, use getLocalVariable(int index, int pc)
|
||||
* instead.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public final LocalVariable getLocalVariable( final int index ) {
|
||||
public final LocalVariable getLocalVariable(final int index) {
|
||||
for (final LocalVariable variable : localVariableTable) {
|
||||
if (variable.getIndex() == index) {
|
||||
return variable;
|
||||
@@ -136,7 +139,6 @@ public class LocalVariableTable extends Attribute {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index the variable slot
|
||||
@@ -144,12 +146,12 @@ public class LocalVariableTable extends Attribute {
|
||||
*
|
||||
* @return the LocalVariable that matches or null if not found
|
||||
*/
|
||||
public final LocalVariable getLocalVariable( final int index, final int pc ) {
|
||||
public final LocalVariable getLocalVariable(final int index, final int pc) {
|
||||
for (final LocalVariable variable : localVariableTable) {
|
||||
if (variable.getIndex() == index) {
|
||||
final int start_pc = variable.getStartPC();
|
||||
final int end_pc = start_pc + variable.getLength();
|
||||
if ((pc >= start_pc) && (pc <= end_pc)) {
|
||||
final int startPc = variable.getStartPC();
|
||||
final int endPc = startPc + variable.getLength();
|
||||
if (pc >= startPc && pc <= endPc) {
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
@@ -157,11 +159,25 @@ public class LocalVariableTable extends Attribute {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public final void setLocalVariableTable( final LocalVariable[] local_variable_table ) {
|
||||
this.localVariableTable = local_variable_table;
|
||||
/**
|
||||
* @return Array of local variables of method.
|
||||
*/
|
||||
public final LocalVariable[] getLocalVariableTable() {
|
||||
return localVariableTable;
|
||||
}
|
||||
|
||||
public final int getTableLength() {
|
||||
return localVariableTable == null ? 0 : localVariableTable.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<LocalVariable> iterator() {
|
||||
return Stream.of(localVariableTable).iterator();
|
||||
}
|
||||
|
||||
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
|
||||
this.localVariableTable = localVariableTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
@@ -177,24 +193,4 @@ public class LocalVariableTable extends Attribute {
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final LocalVariableTable c = (LocalVariableTable) clone();
|
||||
c.localVariableTable = new LocalVariable[localVariableTable.length];
|
||||
for (int i = 0; i < localVariableTable.length; i++) {
|
||||
c.localVariableTable[i] = localVariableTable[i].copy();
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
public final int getTableLength() {
|
||||
return localVariableTable == null ? 0 : localVariableTable.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,12 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
// The new table is used when generic types are about...
|
||||
|
||||
@@ -57,35 +61,49 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
public class LocalVariableTypeTable extends Attribute {
|
||||
public class LocalVariableTypeTable extends Attribute implements Iterable<LocalVariable> {
|
||||
|
||||
private LocalVariable[] localVariableTypeTable; // variables
|
||||
private LocalVariable[] localVariableTypeTable; // variables
|
||||
|
||||
LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException {
|
||||
this(nameIdx, len, (LocalVariable[]) null, cpool);
|
||||
|
||||
final int localVariableTypeTableLength = input.readUnsignedShort();
|
||||
localVariableTypeTable = new LocalVariable[localVariableTypeTableLength];
|
||||
|
||||
for (int i = 0; i < localVariableTypeTableLength; i++) {
|
||||
localVariableTypeTable[i] = new LocalVariable(input, cpool);
|
||||
}
|
||||
}
|
||||
|
||||
public LocalVariableTypeTable(final int nameIndex, final int length, final LocalVariable[] localVariableTypeTable, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE, nameIndex, length, constantPool);
|
||||
this.localVariableTypeTable = localVariableTypeTable != null ? localVariableTypeTable : LocalVariable.EMPTY_ARRAY;
|
||||
Args.requireU2(this.localVariableTypeTable.length, "localVariableTypeTable.length");
|
||||
}
|
||||
|
||||
public LocalVariableTypeTable(final LocalVariableTypeTable c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), c.getConstantPool());
|
||||
}
|
||||
|
||||
public LocalVariableTypeTable(final int name_index, final int length, final LocalVariable[] local_variable_table, final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE, name_index, length, constant_pool);
|
||||
this.localVariableTypeTable = local_variable_table;
|
||||
}
|
||||
|
||||
LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException {
|
||||
this(nameIdx, len, (LocalVariable[]) null, cpool);
|
||||
|
||||
final int local_variable_type_table_length = input.readUnsignedShort();
|
||||
localVariableTypeTable = new LocalVariable[local_variable_type_table_length];
|
||||
|
||||
for (int i = 0; i < local_variable_type_table_length; i++) {
|
||||
localVariableTypeTable[i] = new LocalVariable(input, cpool);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(final Visitor v) {
|
||||
v.visitLocalVariableTypeTable(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final LocalVariableTypeTable c = (LocalVariableTypeTable) clone();
|
||||
|
||||
c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length];
|
||||
Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy());
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
@@ -95,10 +113,6 @@ public class LocalVariableTypeTable extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
public final LocalVariable[] getLocalVariableTypeTable() {
|
||||
return localVariableTypeTable;
|
||||
}
|
||||
|
||||
public final LocalVariable getLocalVariable(final int index) {
|
||||
for (final LocalVariable variable : localVariableTypeTable) {
|
||||
if (variable.getIndex() == index) {
|
||||
@@ -109,8 +123,21 @@ public class LocalVariableTypeTable extends Attribute {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final void setLocalVariableTable(final LocalVariable[] local_variable_table) {
|
||||
this.localVariableTypeTable = local_variable_table;
|
||||
public final LocalVariable[] getLocalVariableTypeTable() {
|
||||
return localVariableTypeTable;
|
||||
}
|
||||
|
||||
public final int getTableLength() {
|
||||
return localVariableTypeTable == null ? 0 : localVariableTypeTable.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<LocalVariable> iterator() {
|
||||
return Stream.of(localVariableTypeTable).iterator();
|
||||
}
|
||||
|
||||
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
|
||||
this.localVariableTypeTable = localVariableTable;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,24 +157,4 @@ public class LocalVariableTypeTable extends Attribute {
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constant_pool) {
|
||||
final LocalVariableTypeTable c = (LocalVariableTypeTable) clone();
|
||||
|
||||
c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length];
|
||||
for (int i = 0; i < localVariableTypeTable.length; i++) {
|
||||
c.localVariableTypeTable[i] = localVariableTypeTable[i].copy();
|
||||
}
|
||||
|
||||
c.setConstantPool(constant_pool);
|
||||
return c;
|
||||
}
|
||||
|
||||
public final int getTableLength() {
|
||||
return localVariableTypeTable == null ? 0 : localVariableTypeTable.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,93 +24,133 @@ import java.io.DataInput;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.generic.Type;
|
||||
import com.sun.org.apache.bcel.internal.util.BCELComparator;
|
||||
|
||||
/**
|
||||
* This class represents the method info structure, i.e., the representation
|
||||
* for a method in the class. See JVM specification for details.
|
||||
* A method has access flags, a name, a signature and a number of attributes.
|
||||
*
|
||||
* This class represents the method info structure, i.e., the representation for a method in the class. See JVM
|
||||
* specification for details. A method has access flags, a name, a signature and a number of attributes.
|
||||
*/
|
||||
public final class Method extends FieldOrMethod {
|
||||
|
||||
/**
|
||||
* Empty array constant.
|
||||
*
|
||||
* @since 6.6.0
|
||||
*/
|
||||
public static final Method[] EMPTY_ARRAY = {};
|
||||
|
||||
private static BCELComparator bcelComparator = new BCELComparator() {
|
||||
|
||||
@Override
|
||||
public boolean equals( final Object o1, final Object o2 ) {
|
||||
public boolean equals(final Object o1, final Object o2) {
|
||||
final Method THIS = (Method) o1;
|
||||
final Method THAT = (Method) o2;
|
||||
return Objects.equals(THIS.getName(), THAT.getName())
|
||||
&& Objects.equals(THIS.getSignature(), THAT.getSignature());
|
||||
return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode( final Object o ) {
|
||||
public int hashCode(final Object o) {
|
||||
final Method THIS = (Method) o;
|
||||
return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
static final Method[] EMPTY_METHOD_ARRAY = {};
|
||||
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
// annotations defined on the parameters of a method
|
||||
private ParameterAnnotationEntry[] parameterAnnotationEntries;
|
||||
|
||||
/**
|
||||
* Empty constructor, all attributes have to be defined via `setXXX'
|
||||
* methods. Use at your own risk.
|
||||
* Empty constructor, all attributes have to be defined via 'setXXX' methods. Use at your own risk.
|
||||
*/
|
||||
public Method() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
Method(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException {
|
||||
super(file, constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
* @param accessFlags Access rights of method
|
||||
* @param nameIndex Points to field name in constant pool
|
||||
* @param signatureIndex Points to encoded signature
|
||||
* @param attributes Collection of attributes
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public Method(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
|
||||
super(accessFlags, nameIndex, signatureIndex, attributes, constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public Method(final Method c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
* @throws ClassFormatException
|
||||
*/
|
||||
Method(final DataInput file, final ConstantPool constant_pool) throws IOException,
|
||||
ClassFormatException {
|
||||
super(file, constant_pool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param access_flags Access rights of method
|
||||
* @param name_index Points to field name in constant pool
|
||||
* @param signature_index Points to encoded signature
|
||||
* @param attributes Collection of attributes
|
||||
* @param constant_pool Array of constants
|
||||
*/
|
||||
public Method(final int access_flags, final int name_index, final int signature_index, final Attribute[] attributes,
|
||||
final ConstantPool constant_pool) {
|
||||
super(access_flags, name_index, signature_index, attributes, constant_pool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitMethod(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this method
|
||||
*/
|
||||
public Method copy(final ConstantPool constantPool) {
|
||||
return (Method) copy_(constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value as defined by given BCELComparator strategy. By default two method objects are said to be equal when
|
||||
* their names and signatures are equal.
|
||||
*
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return bcelComparator.equals(this, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of method argument types
|
||||
*/
|
||||
public Type[] getArgumentTypes() {
|
||||
return Type.getArgumentTypes(getSignature());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Code attribute of method, if any
|
||||
@@ -124,10 +164,9 @@ public final class Method extends FieldOrMethod {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return ExceptionTable attribute of method, if any, i.e., list all
|
||||
* exceptions the method may throw not exception handlers!
|
||||
* @return ExceptionTable attribute of method, if any, i.e., list all exceptions the method may throw not exception
|
||||
* handlers!
|
||||
*/
|
||||
public ExceptionTable getExceptionTable() {
|
||||
for (final Attribute attribute : super.getAttributes()) {
|
||||
@@ -138,21 +177,8 @@ public final class Method extends FieldOrMethod {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/** @return LocalVariableTable of code attribute if any, i.e. the call is forwarded
|
||||
* to the Code atribute.
|
||||
*/
|
||||
public LocalVariableTable getLocalVariableTable() {
|
||||
final Code code = getCode();
|
||||
if (code == null) {
|
||||
return null;
|
||||
}
|
||||
return code.getLocalVariableTable();
|
||||
}
|
||||
|
||||
|
||||
/** @return LineNumberTable of code attribute if any, i.e. the call is forwarded
|
||||
* to the Code atribute.
|
||||
/**
|
||||
* @return LineNumberTable of code attribute if any, i.e. the call is forwarded to the Code atribute.
|
||||
*/
|
||||
public LineNumberTable getLineNumberTable() {
|
||||
final Code code = getCode();
|
||||
@@ -162,102 +188,15 @@ public final class Method extends FieldOrMethod {
|
||||
return code.getLineNumberTable();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return string representation close to declaration format,
|
||||
* `public static void main(String[] args) throws IOException', e.g.
|
||||
*
|
||||
* @return String representation of the method.
|
||||
* @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code atribute.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
final String access = Utility.accessToString(super.getAccessFlags());
|
||||
// Get name and signature from constant pool
|
||||
ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(super.getSignatureIndex(), Const.CONSTANT_Utf8);
|
||||
String signature = c.getBytes();
|
||||
c = (ConstantUtf8) super.getConstantPool().getConstant(super.getNameIndex(), Const.CONSTANT_Utf8);
|
||||
final String name = c.getBytes();
|
||||
signature = Utility.methodSignatureToString(signature, name, access, true,
|
||||
getLocalVariableTable());
|
||||
final StringBuilder buf = new StringBuilder(signature);
|
||||
for (final Attribute attribute : super.getAttributes()) {
|
||||
if (!((attribute instanceof Code) || (attribute instanceof ExceptionTable))) {
|
||||
buf.append(" [").append(attribute).append("]");
|
||||
}
|
||||
public LocalVariableTable getLocalVariableTable() {
|
||||
final Code code = getCode();
|
||||
if (code == null) {
|
||||
return null;
|
||||
}
|
||||
final ExceptionTable e = getExceptionTable();
|
||||
if (e != null) {
|
||||
final String str = e.toString();
|
||||
if (!str.isEmpty()) {
|
||||
buf.append("\n\t\tthrows ").append(str);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this method
|
||||
*/
|
||||
public Method copy( final ConstantPool _constant_pool ) {
|
||||
return (Method) copy_(_constant_pool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return return type of method
|
||||
*/
|
||||
public Type getReturnType() {
|
||||
return Type.getReturnType(getSignature());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array of method argument types
|
||||
*/
|
||||
public Type[] getArgumentTypes() {
|
||||
return Type.getArgumentTypes(getSignature());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator( final BCELComparator comparator ) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return value as defined by given BCELComparator strategy.
|
||||
* By default two method objects are said to be equal when
|
||||
* their names and signatures are equal.
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals( final Object obj ) {
|
||||
return bcelComparator.equals(this, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return value as defined by given BCELComparator strategy.
|
||||
* By default return the hashcode of the method's name XOR signature.
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return bcelComparator.hashCode(this);
|
||||
return code.getLocalVariableTable();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,4 +209,53 @@ public final class Method extends FieldOrMethod {
|
||||
}
|
||||
return parameterAnnotationEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return return type of method
|
||||
*/
|
||||
public Type getReturnType() {
|
||||
return Type.getReturnType(getSignature());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR
|
||||
* signature.
|
||||
*
|
||||
* @see Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return bcelComparator.hashCode(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string representation close to declaration format, 'public static void main(String[] args) throws
|
||||
* IOException', e.g.
|
||||
*
|
||||
* @return String representation of the method.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
final String access = Utility.accessToString(super.getAccessFlags());
|
||||
// Get name and signature from constant pool
|
||||
ConstantUtf8 c = super.getConstantPool().getConstantUtf8(super.getSignatureIndex());
|
||||
String signature = c.getBytes();
|
||||
c = super.getConstantPool().getConstantUtf8(super.getNameIndex());
|
||||
final String name = c.getBytes();
|
||||
signature = Utility.methodSignatureToString(signature, name, access, true, getLocalVariableTable());
|
||||
final StringBuilder buf = new StringBuilder(signature);
|
||||
for (final Attribute attribute : super.getAttributes()) {
|
||||
if (!(attribute instanceof Code || attribute instanceof ExceptionTable)) {
|
||||
buf.append(" [").append(attribute).append("]");
|
||||
}
|
||||
}
|
||||
final ExceptionTable e = getExceptionTable();
|
||||
if (e != null) {
|
||||
final String str = e.toString();
|
||||
if (!str.isEmpty()) {
|
||||
buf.append("\n\t\tthrows ").append(str);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
/**
|
||||
* Entry of the parameters table.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24">
|
||||
* The class File Format : The MethodParameters Attribute</a>
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24"> The class File Format :
|
||||
* The MethodParameters Attribute</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public class MethodParameter implements Cloneable {
|
||||
public class MethodParameter implements Cloneable, Node {
|
||||
|
||||
/** Index of the CONSTANT_Utf8_info structure in the constant_pool table representing the name of the parameter */
|
||||
private int nameIndex;
|
||||
@@ -49,67 +49,19 @@ public class MethodParameter implements Cloneable {
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param input Input stream
|
||||
* @throws java.io.IOException
|
||||
* @throws ClassFormatException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
MethodParameter(final DataInput input) throws IOException {
|
||||
nameIndex = input.readUnsignedShort();
|
||||
accessFlags = input.readUnsignedShort();
|
||||
}
|
||||
|
||||
public int getNameIndex() {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
public void setNameIndex(final int name_index) {
|
||||
this.nameIndex = name_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the parameter.
|
||||
*/
|
||||
public String getParameterName(final ConstantPool constant_pool) {
|
||||
if (nameIndex == 0) {
|
||||
return null;
|
||||
}
|
||||
return ((ConstantUtf8) constant_pool.getConstant(nameIndex, Const.CONSTANT_Utf8)).getBytes();
|
||||
}
|
||||
|
||||
public int getAccessFlags() {
|
||||
return accessFlags;
|
||||
}
|
||||
|
||||
public void setAccessFlags(final int access_flags) {
|
||||
this.accessFlags = access_flags;
|
||||
}
|
||||
|
||||
public boolean isFinal() {
|
||||
return (accessFlags & Const.ACC_FINAL) != 0;
|
||||
}
|
||||
|
||||
public boolean isSynthetic() {
|
||||
return (accessFlags & Const.ACC_SYNTHETIC) != 0;
|
||||
}
|
||||
|
||||
public boolean isMandated() {
|
||||
return (accessFlags & Const.ACC_MANDATED) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(final Visitor v) {
|
||||
v.visitMethodParameter(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump object to file stream on binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
*/
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(nameIndex);
|
||||
file.writeShort(accessFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@@ -121,4 +73,53 @@ public class MethodParameter implements Cloneable {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump object to file stream on binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public final void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(nameIndex);
|
||||
file.writeShort(accessFlags);
|
||||
}
|
||||
|
||||
public int getAccessFlags() {
|
||||
return accessFlags;
|
||||
}
|
||||
|
||||
public int getNameIndex() {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the parameter.
|
||||
*/
|
||||
public String getParameterName(final ConstantPool constantPool) {
|
||||
if (nameIndex == 0) {
|
||||
return null;
|
||||
}
|
||||
return constantPool.getConstantUtf8(nameIndex).getBytes();
|
||||
}
|
||||
|
||||
public boolean isFinal() {
|
||||
return (accessFlags & Const.ACC_FINAL) != 0;
|
||||
}
|
||||
|
||||
public boolean isMandated() {
|
||||
return (accessFlags & Const.ACC_MANDATED) != 0;
|
||||
}
|
||||
|
||||
public boolean isSynthetic() {
|
||||
return (accessFlags & Const.ACC_SYNTHETIC) != 0;
|
||||
}
|
||||
|
||||
public void setAccessFlags(final int accessFlags) {
|
||||
this.accessFlags = accessFlags;
|
||||
}
|
||||
|
||||
public void setNameIndex(final int nameIndex) {
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,52 +24,50 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents a MethodParameters attribute.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24">
|
||||
* The class File Format : The MethodParameters Attribute</a>
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24"> The class File Format :
|
||||
* The MethodParameters Attribute</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public class MethodParameters extends Attribute {
|
||||
public class MethodParameters extends Attribute implements Iterable<MethodParameter> {
|
||||
|
||||
private MethodParameter[] parameters = new MethodParameter[0];
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
private static final MethodParameter[] EMPTY_METHOD_PARAMETER_ARRAY = {};
|
||||
|
||||
MethodParameters(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
super(Const.ATTR_METHOD_PARAMETERS, name_index, length, constant_pool);
|
||||
private MethodParameter[] parameters = EMPTY_METHOD_PARAMETER_ARRAY;
|
||||
|
||||
final int parameters_count = input.readUnsignedByte();
|
||||
parameters = new MethodParameter[parameters_count];
|
||||
for (int i = 0; i < parameters_count; i++) {
|
||||
MethodParameters(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
super(Const.ATTR_METHOD_PARAMETERS, nameIndex, length, constantPool);
|
||||
|
||||
final int parameterCount = input.readUnsignedByte();
|
||||
parameters = new MethodParameter[parameterCount];
|
||||
for (int i = 0; i < parameterCount; i++) {
|
||||
parameters[i] = new MethodParameter(input);
|
||||
}
|
||||
}
|
||||
|
||||
public MethodParameter[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(final MethodParameter[] parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(final Visitor v) {
|
||||
v.visitMethodParameters(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool _constant_pool) {
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final MethodParameters c = (MethodParameters) clone();
|
||||
c.parameters = new MethodParameter[parameters.length];
|
||||
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
c.parameters[i] = parameters[i].copy();
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
Arrays.setAll(c.parameters, i -> parameters[i].copy());
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -77,14 +75,27 @@ public class MethodParameters extends Attribute {
|
||||
* Dump method parameters attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeByte(parameters.length);
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeByte(parameters.length);
|
||||
for (final MethodParameter parameter : parameters) {
|
||||
parameter.dump(file);
|
||||
}
|
||||
}
|
||||
|
||||
public MethodParameter[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<MethodParameter> iterator() {
|
||||
return Stream.of(parameters).iterator();
|
||||
}
|
||||
|
||||
public void setParameters(final MethodParameter[] parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,19 +24,26 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and represents the list of
|
||||
* modules required, exported, opened or provided by a module.
|
||||
* There may be at most one Module attribute in a ClassFile structure.
|
||||
* This class is derived from <em>Attribute</em> and represents the list of modules required, exported, opened or
|
||||
* provided by a module. There may be at most one Module attribute in a ClassFile structure.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
* @since 6.4.0
|
||||
*/
|
||||
public final class Module extends Attribute {
|
||||
|
||||
/**
|
||||
* The module file name extension.
|
||||
*
|
||||
* @since 6.7.0
|
||||
*/
|
||||
public static final String EXTENSION = ".jmod";
|
||||
|
||||
private final int moduleNameIndex;
|
||||
private final int moduleFlags;
|
||||
private final int moduleVersionIndex;
|
||||
@@ -50,34 +57,35 @@ public final class Module extends Attribute {
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* @param name_index Index in constant pool
|
||||
*
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
Module(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
super(Const.ATTR_MODULE, name_index, length, constant_pool);
|
||||
Module(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
super(Const.ATTR_MODULE, nameIndex, length, constantPool);
|
||||
|
||||
moduleNameIndex = input.readUnsignedShort();
|
||||
moduleFlags = input.readUnsignedShort();
|
||||
moduleVersionIndex = input.readUnsignedShort();
|
||||
|
||||
final int requires_count = input.readUnsignedShort();
|
||||
requiresTable = new ModuleRequires[requires_count];
|
||||
for (int i = 0; i < requires_count; i++) {
|
||||
final int requiresCount = input.readUnsignedShort();
|
||||
requiresTable = new ModuleRequires[requiresCount];
|
||||
for (int i = 0; i < requiresCount; i++) {
|
||||
requiresTable[i] = new ModuleRequires(input);
|
||||
}
|
||||
|
||||
final int exports_count = input.readUnsignedShort();
|
||||
exportsTable = new ModuleExports[exports_count];
|
||||
for (int i = 0; i < exports_count; i++) {
|
||||
final int exportsCount = input.readUnsignedShort();
|
||||
exportsTable = new ModuleExports[exportsCount];
|
||||
for (int i = 0; i < exportsCount; i++) {
|
||||
exportsTable[i] = new ModuleExports(input);
|
||||
}
|
||||
|
||||
final int opens_count = input.readUnsignedShort();
|
||||
opensTable = new ModuleOpens[opens_count];
|
||||
for (int i = 0; i < opens_count; i++) {
|
||||
final int opensCount = input.readUnsignedShort();
|
||||
opensTable = new ModuleOpens[opensCount];
|
||||
for (int i = 0; i < opensCount; i++) {
|
||||
opensTable[i] = new ModuleOpens(input);
|
||||
}
|
||||
|
||||
@@ -87,72 +95,57 @@ public final class Module extends Attribute {
|
||||
usesIndex[i] = input.readUnsignedShort();
|
||||
}
|
||||
|
||||
final int provides_count = input.readUnsignedShort();
|
||||
providesTable = new ModuleProvides[provides_count];
|
||||
for (int i = 0; i < provides_count; i++) {
|
||||
final int providesCount = input.readUnsignedShort();
|
||||
providesTable = new ModuleProvides[providesCount];
|
||||
for (int i = 0; i < providesCount; i++) {
|
||||
providesTable[i] = new ModuleProvides(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitModule(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* @return table of required modules
|
||||
* @see ModuleRequires
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
public ModuleRequires[] getRequiresTable() {
|
||||
return requiresTable;
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final Module c = (Module) clone();
|
||||
|
||||
c.requiresTable = new ModuleRequires[requiresTable.length];
|
||||
Arrays.setAll(c.requiresTable, i -> requiresTable[i].copy());
|
||||
|
||||
c.exportsTable = new ModuleExports[exportsTable.length];
|
||||
Arrays.setAll(c.exportsTable, i -> exportsTable[i].copy());
|
||||
|
||||
c.opensTable = new ModuleOpens[opensTable.length];
|
||||
Arrays.setAll(c.opensTable, i -> opensTable[i].copy());
|
||||
|
||||
c.providesTable = new ModuleProvides[providesTable.length];
|
||||
Arrays.setAll(c.providesTable, i -> providesTable[i].copy());
|
||||
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return table of exported interfaces
|
||||
* @see ModuleExports
|
||||
*/
|
||||
public ModuleExports[] getExportsTable() {
|
||||
return exportsTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return table of provided interfaces
|
||||
* @see ModuleOpens
|
||||
*/
|
||||
public ModuleOpens[] getOpensTable() {
|
||||
return opensTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return table of provided interfaces
|
||||
* @see ModuleProvides
|
||||
*/
|
||||
public ModuleProvides[] getProvidesTable() {
|
||||
return providesTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump Module attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
|
||||
file.writeShort(moduleNameIndex);
|
||||
@@ -185,6 +178,37 @@ public final class Module extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return table of exported interfaces
|
||||
* @see ModuleExports
|
||||
*/
|
||||
public ModuleExports[] getExportsTable() {
|
||||
return exportsTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return table of provided interfaces
|
||||
* @see ModuleOpens
|
||||
*/
|
||||
public ModuleOpens[] getOpensTable() {
|
||||
return opensTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return table of provided interfaces
|
||||
* @see ModuleProvides
|
||||
*/
|
||||
public ModuleProvides[] getProvidesTable() {
|
||||
return providesTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return table of required modules
|
||||
* @see ModuleRequires
|
||||
*/
|
||||
public ModuleRequires[] getRequiresTable() {
|
||||
return requiresTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation, i.e., a list of packages.
|
||||
@@ -194,10 +218,10 @@ public final class Module extends Attribute {
|
||||
final ConstantPool cp = super.getConstantPool();
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
buf.append("Module:\n");
|
||||
buf.append(" name: ") .append(cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module).replace('/', '.')).append("\n");
|
||||
buf.append(" flags: ") .append(String.format("%04x", moduleFlags)).append("\n");
|
||||
buf.append(" name: ").append(Utility.pathToPackage(cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module))).append("\n");
|
||||
buf.append(" flags: ").append(String.format("%04x", moduleFlags)).append("\n");
|
||||
final String version = moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8);
|
||||
buf.append(" version: ") .append(version).append("\n");
|
||||
buf.append(" version: ").append(version).append("\n");
|
||||
|
||||
buf.append(" requires(").append(requiresTable.length).append("):\n");
|
||||
for (final ModuleRequires module : requiresTable) {
|
||||
@@ -216,8 +240,8 @@ public final class Module extends Attribute {
|
||||
|
||||
buf.append(" uses(").append(usesIndex.length).append("):\n");
|
||||
for (final int index : usesIndex) {
|
||||
final String class_name = cp.getConstantString(index, Const.CONSTANT_Class);
|
||||
buf.append(" ").append(Utility.compactClassName(class_name, false)).append("\n");
|
||||
final String className = cp.getConstantString(index, Const.CONSTANT_Class);
|
||||
buf.append(" ").append(Utility.compactClassName(className, false)).append("\n");
|
||||
}
|
||||
|
||||
buf.append(" provides(").append(providesTable.length).append("):\n");
|
||||
@@ -225,38 +249,6 @@ public final class Module extends Attribute {
|
||||
buf.append(" ").append(module.toString(cp)).append("\n");
|
||||
}
|
||||
|
||||
return buf.substring(0, buf.length()-1); // remove the last newline
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final Module c = (Module) clone();
|
||||
|
||||
c.requiresTable = new ModuleRequires[requiresTable.length];
|
||||
for (int i = 0; i < requiresTable.length; i++) {
|
||||
c.requiresTable[i] = requiresTable[i].copy();
|
||||
}
|
||||
|
||||
c.exportsTable = new ModuleExports[exportsTable.length];
|
||||
for (int i = 0; i < exportsTable.length; i++) {
|
||||
c.exportsTable[i] = exportsTable[i].copy();
|
||||
}
|
||||
|
||||
c.opensTable = new ModuleOpens[opensTable.length];
|
||||
for (int i = 0; i < opensTable.length; i++) {
|
||||
c.opensTable[i] = opensTable[i].copy();
|
||||
}
|
||||
|
||||
c.providesTable = new ModuleProvides[providesTable.length];
|
||||
for (int i = 0; i < providesTable.length; i++) {
|
||||
c.providesTable[i] = providesTable[i].copy();
|
||||
}
|
||||
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
return buf.substring(0, buf.length() - 1); // remove the last newline
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,19 +28,18 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents an entry in the exports table of the Module attribute.
|
||||
* Each entry describes a package which may open the parent module.
|
||||
* This class represents an entry in the exports table of the Module attribute. Each entry describes a package which may
|
||||
* open the parent module.
|
||||
*
|
||||
* @see Module
|
||||
* @see Module
|
||||
* @since 6.4.0
|
||||
*/
|
||||
public final class ModuleExports implements Cloneable, Node {
|
||||
|
||||
private final int exportsIndex; // points to CONSTANT_Package_info
|
||||
private final int exportsIndex; // points to CONSTANT_Package_info
|
||||
private final int exportsFlags;
|
||||
private final int exportsToCount;
|
||||
private final int[] exportsToIndex; // points to CONSTANT_Module_info
|
||||
|
||||
private final int[] exportsToIndex; // points to CONSTANT_Module_info
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
@@ -58,63 +57,19 @@ public final class ModuleExports implements Cloneable, Node {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitModuleExports(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* Dump table entry to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
file.writeShort(exportsIndex);
|
||||
file.writeShort(exportsFlags);
|
||||
file.writeShort(exportsToCount);
|
||||
for (final int entry : exportsToIndex) {
|
||||
file.writeShort(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "exports(" + exportsIndex + ", " + exportsFlags + ", " + exportsToCount + ", ...)";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString( final ConstantPool constant_pool ) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final String package_name = constant_pool.constantToString(exportsIndex, Const.CONSTANT_Package);
|
||||
buf.append(Utility.compactClassName(package_name, false));
|
||||
buf.append(", ").append(String.format("%04x", exportsFlags));
|
||||
buf.append(", to(").append(exportsToCount).append("):\n");
|
||||
for (final int index : exportsToIndex) {
|
||||
final String module_name = constant_pool.getConstantString(index, Const.CONSTANT_Module);
|
||||
buf.append(" ").append(Utility.compactClassName(module_name, false)).append("\n");
|
||||
}
|
||||
return buf.substring(0, buf.length()-1); // remove the last newline
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@@ -126,4 +81,43 @@ public final class ModuleExports implements Cloneable, Node {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump table entry to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(exportsIndex);
|
||||
file.writeShort(exportsFlags);
|
||||
file.writeShort(exportsToCount);
|
||||
for (final int entry : exportsToIndex) {
|
||||
file.writeShort(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "exports(" + exportsIndex + ", " + exportsFlags + ", " + exportsToCount + ", ...)";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString(final ConstantPool constantPool) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final String packageName = constantPool.constantToString(exportsIndex, Const.CONSTANT_Package);
|
||||
buf.append(Utility.compactClassName(packageName, false));
|
||||
buf.append(", ").append(String.format("%04x", exportsFlags));
|
||||
buf.append(", to(").append(exportsToCount).append("):\n");
|
||||
for (final int index : exportsToIndex) {
|
||||
final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module);
|
||||
buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n");
|
||||
}
|
||||
return buf.substring(0, buf.length() - 1); // remove the last newline
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,66 +26,73 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and indicates the main class of a module.
|
||||
* There may be at most one ModuleMainClass attribute in a ClassFile structure.
|
||||
* This class is derived from <em>Attribute</em> and indicates the main class of a module. There may be at most one
|
||||
* ModuleMainClass attribute in a ClassFile structure.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class ModuleMainClass extends Attribute {
|
||||
|
||||
private int mainClassIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
*/
|
||||
public ModuleMainClass(final ModuleMainClass c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getHostClassIndex(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param mainClassIndex Host class index
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public ModuleMainClass(final int name_index, final int length, final int mainClassIndex,
|
||||
final ConstantPool constantPool) {
|
||||
super(Const.ATTR_NEST_MEMBERS, name_index, length, constantPool);
|
||||
this.mainClassIndex = mainClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ModuleMainClass(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, 0, constantPool);
|
||||
mainClassIndex = input.readUnsignedShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param mainClassIndex Host class index
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public ModuleMainClass(final int nameIndex, final int length, final int mainClassIndex, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool);
|
||||
this.mainClassIndex = Args.requireU2(mainClassIndex, "mainClassIndex");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public ModuleMainClass(final ModuleMainClass c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getHostClassIndex(), c.getConstantPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. I.e.,
|
||||
* the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitModuleMainClass(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final ModuleMainClass c = (ModuleMainClass) clone();
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump ModuleMainClass attribute to file stream in binary format.
|
||||
@@ -94,12 +101,11 @@ public final class ModuleMainClass extends Attribute {
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(mainClassIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return index into constant pool of host class name.
|
||||
*/
|
||||
@@ -107,15 +113,13 @@ public final class ModuleMainClass extends Attribute {
|
||||
return mainClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mainClassIndex the host class index
|
||||
*/
|
||||
public void setHostClassIndex( final int mainClassIndex ) {
|
||||
public void setHostClassIndex(final int mainClassIndex) {
|
||||
this.mainClassIndex = mainClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@@ -123,19 +127,8 @@ public final class ModuleMainClass extends Attribute {
|
||||
public String toString() {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
buf.append("ModuleMainClass: ");
|
||||
final String class_name = super.getConstantPool().getConstantString(mainClassIndex, Const.CONSTANT_Class);
|
||||
buf.append(Utility.compactClassName(class_name, false));
|
||||
final String className = super.getConstantPool().getConstantString(mainClassIndex, Const.CONSTANT_Class);
|
||||
buf.append(Utility.compactClassName(className, false));
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final ModuleMainClass c = (ModuleMainClass) clone();
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,19 +28,18 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents an entry in the opens table of the Module attribute.
|
||||
* Each entry describes a package which the parent module opens.
|
||||
* This class represents an entry in the opens table of the Module attribute. Each entry describes a package which the
|
||||
* parent module opens.
|
||||
*
|
||||
* @see Module
|
||||
* @see Module
|
||||
* @since 6.4.0
|
||||
*/
|
||||
public final class ModuleOpens implements Cloneable, Node {
|
||||
|
||||
private final int opensIndex; // points to CONSTANT_Package_info
|
||||
private final int opensIndex; // points to CONSTANT_Package_info
|
||||
private final int opensFlags;
|
||||
private final int opensToCount;
|
||||
private final int[] opensToIndex; // points to CONSTANT_Module_info
|
||||
|
||||
private final int[] opensToIndex; // points to CONSTANT_Module_info
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
@@ -58,63 +57,19 @@ public final class ModuleOpens implements Cloneable, Node {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitModuleOpens(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* Dump table entry to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
file.writeShort(opensIndex);
|
||||
file.writeShort(opensFlags);
|
||||
file.writeShort(opensToCount);
|
||||
for (final int entry : opensToIndex) {
|
||||
file.writeShort(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "opens(" + opensIndex + ", " + opensFlags + ", " + opensToCount + ", ...)";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString( final ConstantPool constant_pool ) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final String package_name = constant_pool.constantToString(opensIndex, Const.CONSTANT_Package);
|
||||
buf.append(Utility.compactClassName(package_name, false));
|
||||
buf.append(", ").append(String.format("%04x", opensFlags));
|
||||
buf.append(", to(").append(opensToCount).append("):\n");
|
||||
for (final int index : opensToIndex) {
|
||||
final String module_name = constant_pool.getConstantString(index, Const.CONSTANT_Module);
|
||||
buf.append(" ").append(Utility.compactClassName(module_name, false)).append("\n");
|
||||
}
|
||||
return buf.substring(0, buf.length()-1); // remove the last newline
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@@ -126,4 +81,43 @@ public final class ModuleOpens implements Cloneable, Node {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump table entry to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(opensIndex);
|
||||
file.writeShort(opensFlags);
|
||||
file.writeShort(opensToCount);
|
||||
for (final int entry : opensToIndex) {
|
||||
file.writeShort(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "opens(" + opensIndex + ", " + opensFlags + ", " + opensToCount + ", ...)";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString(final ConstantPool constantPool) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final String packageName = constantPool.constantToString(opensIndex, Const.CONSTANT_Package);
|
||||
buf.append(Utility.compactClassName(packageName, false));
|
||||
buf.append(", ").append(String.format("%04x", opensFlags));
|
||||
buf.append(", to(").append(opensToCount).append("):\n");
|
||||
for (final int index : opensToIndex) {
|
||||
final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module);
|
||||
buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n");
|
||||
}
|
||||
return buf.substring(0, buf.length() - 1); // remove the last newline
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -24,81 +23,94 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and represents the list of packages that are exported or opened by the Module attribute.
|
||||
* There may be at most one ModulePackages attribute in a ClassFile structure.
|
||||
* This class is derived from <em>Attribute</em> and represents the list of packages that are exported or opened by the
|
||||
* Module attribute. There may be at most one ModulePackages attribute in a ClassFile structure.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public final class ModulePackages extends Attribute {
|
||||
|
||||
private int[] packageIndexTable;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public ModulePackages(final ModulePackages c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getPackageIndexTable(), c.getConstantPool());
|
||||
ModulePackages(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (int[]) null, constantPool);
|
||||
final int packageCount = input.readUnsignedShort();
|
||||
packageIndexTable = new int[packageCount];
|
||||
for (int i = 0; i < packageCount; i++) {
|
||||
packageIndexTable[i] = input.readUnsignedShort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param packageIndexTable Table of indices in constant pool
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable,
|
||||
final ConstantPool constantPool) {
|
||||
public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_MODULE_PACKAGES, nameIndex, length, constantPool);
|
||||
this.packageIndexTable = packageIndexTable != null ? packageIndexTable : new int[0];
|
||||
this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY;
|
||||
Args.requireU2(this.packageIndexTable.length, "packageIndexTable.length");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* @param name_index Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
ModulePackages(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
this(name_index, length, (int[]) null, constant_pool);
|
||||
final int number_of_packages = input.readUnsignedShort();
|
||||
packageIndexTable = new int[number_of_packages];
|
||||
for (int i = 0; i < number_of_packages; i++) {
|
||||
packageIndexTable[i] = input.readUnsignedShort();
|
||||
}
|
||||
public ModulePackages(final ModulePackages c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getPackageIndexTable(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitModulePackages(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final ModulePackages c = (ModulePackages) clone();
|
||||
if (packageIndexTable != null) {
|
||||
c.packageIndexTable = packageIndexTable.clone();
|
||||
}
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump ModulePackages attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(packageIndexTable.length);
|
||||
for (final int index : packageIndexTable) {
|
||||
@@ -106,15 +118,6 @@ public final class ModulePackages extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array of indices into constant pool of package names.
|
||||
*/
|
||||
public int[] getPackageIndexTable() {
|
||||
return packageIndexTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Length of package table.
|
||||
*/
|
||||
@@ -122,29 +125,29 @@ public final class ModulePackages extends Attribute {
|
||||
return packageIndexTable == null ? 0 : packageIndexTable.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of indices into constant pool of package names.
|
||||
*/
|
||||
public int[] getPackageIndexTable() {
|
||||
return packageIndexTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string array of package names
|
||||
*/
|
||||
public String[] getPackageNames() {
|
||||
final String[] names = new String[packageIndexTable.length];
|
||||
for (int i = 0; i < packageIndexTable.length; i++) {
|
||||
names[i] = super.getConstantPool().getConstantString(packageIndexTable[i],
|
||||
Const.CONSTANT_Package).replace('/', '.');
|
||||
}
|
||||
Arrays.setAll(names, i -> Utility.pathToPackage(super.getConstantPool().getConstantString(packageIndexTable[i], Const.CONSTANT_Package)));
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param packageIndexTable the list of package indexes
|
||||
* Also redefines number_of_packages according to table length.
|
||||
* @param packageIndexTable the list of package indexes Also redefines number_of_packages according to table length.
|
||||
*/
|
||||
public void setPackageIndexTable( final int[] packageIndexTable ) {
|
||||
this.packageIndexTable = packageIndexTable != null ? packageIndexTable : new int[0];
|
||||
public void setPackageIndexTable(final int[] packageIndexTable) {
|
||||
this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation, i.e., a list of packages.
|
||||
*/
|
||||
@@ -155,25 +158,9 @@ public final class ModulePackages extends Attribute {
|
||||
buf.append(packageIndexTable.length);
|
||||
buf.append("):\n");
|
||||
for (final int index : packageIndexTable) {
|
||||
final String package_name = super.getConstantPool().getConstantString(index, Const.CONSTANT_Package);
|
||||
buf.append(" ").append(Utility.compactClassName(package_name, false)).append("\n");
|
||||
final String packageName = super.getConstantPool().getConstantString(index, Const.CONSTANT_Package);
|
||||
buf.append(" ").append(Utility.compactClassName(packageName, false)).append("\n");
|
||||
}
|
||||
return buf.substring(0, buf.length()-1); // remove the last newline
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final ModulePackages c = (ModulePackages) clone();
|
||||
if (packageIndexTable != null) {
|
||||
c.packageIndexTable = new int[packageIndexTable.length];
|
||||
System.arraycopy(packageIndexTable, 0, c.packageIndexTable, 0,
|
||||
packageIndexTable.length);
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
return buf.substring(0, buf.length() - 1); // remove the last newline
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,18 +28,17 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents an entry in the provides table of the Module attribute.
|
||||
* Each entry describes a service implementation that the parent module provides.
|
||||
* This class represents an entry in the provides table of the Module attribute. Each entry describes a service
|
||||
* implementation that the parent module provides.
|
||||
*
|
||||
* @see Module
|
||||
* @see Module
|
||||
* @since 6.4.0
|
||||
*/
|
||||
public final class ModuleProvides implements Cloneable, Node {
|
||||
|
||||
private final int providesIndex; // points to CONSTANT_Class_info
|
||||
private final int providesIndex; // points to CONSTANT_Class_info
|
||||
private final int providesWithCount;
|
||||
private final int[] providesWithIndex; // points to CONSTANT_Class_info
|
||||
|
||||
private final int[] providesWithIndex; // points to CONSTANT_Class_info
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
@@ -56,61 +55,19 @@ public final class ModuleProvides implements Cloneable, Node {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitModuleProvides(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* Dump table entry to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
file.writeShort(providesIndex);
|
||||
file.writeShort(providesWithCount);
|
||||
for (final int entry : providesWithIndex) {
|
||||
file.writeShort(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "provides(" + providesIndex + ", " + providesWithCount + ", ...)";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString( final ConstantPool constant_pool ) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final String interface_name = constant_pool.constantToString(providesIndex, Const.CONSTANT_Class);
|
||||
buf.append(Utility.compactClassName(interface_name, false));
|
||||
buf.append(", with(").append(providesWithCount).append("):\n");
|
||||
for (final int index : providesWithIndex) {
|
||||
final String class_name = constant_pool.getConstantString(index, Const.CONSTANT_Class);
|
||||
buf.append(" ").append(Utility.compactClassName(class_name, false)).append("\n");
|
||||
}
|
||||
return buf.substring(0, buf.length()-1); // remove the last newline
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@@ -122,4 +79,41 @@ public final class ModuleProvides implements Cloneable, Node {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump table entry to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(providesIndex);
|
||||
file.writeShort(providesWithCount);
|
||||
for (final int entry : providesWithIndex) {
|
||||
file.writeShort(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "provides(" + providesIndex + ", " + providesWithCount + ", ...)";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString(final ConstantPool constantPool) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final String interfaceName = constantPool.constantToString(providesIndex, Const.CONSTANT_Class);
|
||||
buf.append(Utility.compactClassName(interfaceName, false));
|
||||
buf.append(", with(").append(providesWithCount).append("):\n");
|
||||
for (final int index : providesWithIndex) {
|
||||
final String className = constantPool.getConstantString(index, Const.CONSTANT_Class);
|
||||
buf.append(" ").append(Utility.compactClassName(className, false)).append("\n");
|
||||
}
|
||||
return buf.substring(0, buf.length() - 1); // remove the last newline
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,18 +28,17 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents an entry in the requires table of the Module attribute.
|
||||
* Each entry describes a module on which the parent module depends.
|
||||
* This class represents an entry in the requires table of the Module attribute. Each entry describes a module on which
|
||||
* the parent module depends.
|
||||
*
|
||||
* @see Module
|
||||
* @see Module
|
||||
* @since 6.4.0
|
||||
*/
|
||||
public final class ModuleRequires implements Cloneable, Node {
|
||||
|
||||
private final int requiresIndex; // points to CONSTANT_Module_info
|
||||
private final int requiresIndex; // points to CONSTANT_Module_info
|
||||
private final int requiresFlags;
|
||||
private final int requiresVersionIndex; // either 0 or points to CONSTANT_Utf8_info
|
||||
|
||||
private final int requiresVersionIndex; // either 0 or points to CONSTANT_Utf8_info
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
@@ -53,57 +52,19 @@ public final class ModuleRequires implements Cloneable, Node {
|
||||
requiresVersionIndex = file.readUnsignedShort();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitModuleRequires(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* Dump table entry to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
file.writeShort(requiresIndex);
|
||||
file.writeShort(requiresFlags);
|
||||
file.writeShort(requiresVersionIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "requires(" + requiresIndex + ", " + String.format("%04x", requiresFlags) + ", " + requiresVersionIndex + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString( final ConstantPool constant_pool ) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final String module_name = constant_pool.constantToString(requiresIndex, Const.CONSTANT_Module);
|
||||
buf.append(Utility.compactClassName(module_name, false));
|
||||
buf.append(", ").append(String.format("%04x", requiresFlags));
|
||||
final String version = requiresVersionIndex == 0 ? "0" : constant_pool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8);
|
||||
buf.append(", ").append(version);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@@ -115,4 +76,37 @@ public final class ModuleRequires implements Cloneable, Node {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump table entry to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O Exception occurs in writeShort
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeShort(requiresIndex);
|
||||
file.writeShort(requiresFlags);
|
||||
file.writeShort(requiresVersionIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "requires(" + requiresIndex + ", " + String.format("%04x", requiresFlags) + ", " + requiresVersionIndex + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Resolved string representation
|
||||
*/
|
||||
public String toString(final ConstantPool constantPool) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final String moduleName = constantPool.constantToString(requiresIndex, Const.CONSTANT_Module);
|
||||
buf.append(Utility.compactClassName(moduleName, false));
|
||||
buf.append(", ").append(String.format("%04x", requiresFlags));
|
||||
final String version = requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8);
|
||||
buf.append(", ").append(version);
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,67 +26,73 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and records the nest host of the nest
|
||||
* to which the current class or interface claims to belong.
|
||||
* There may be at most one NestHost attribute in a ClassFile structure.
|
||||
* This class is derived from <em>Attribute</em> and records the nest host of the nest to which the current class or
|
||||
* interface claims to belong. There may be at most one NestHost attribute in a ClassFile structure.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class NestHost extends Attribute {
|
||||
|
||||
private int hostClassIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
* Constructs object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public NestHost(final NestHost c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getHostClassIndex(), c.getConstantPool());
|
||||
NestHost(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, 0, constantPool);
|
||||
hostClassIndex = input.readUnsignedShort();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param hostClassIndex Host class index
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public NestHost(final int nameIndex, final int length, final int hostClassIndex,
|
||||
final ConstantPool constantPool) {
|
||||
public NestHost(final int nameIndex, final int length, final int hostClassIndex, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool);
|
||||
this.hostClassIndex = hostClassIndex;
|
||||
this.hostClassIndex = Args.requireU2(hostClassIndex, "hostClassIndex");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs object from input stream.
|
||||
* @param name_index Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* Initializes from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
NestHost(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
this(name_index, length, 0, constant_pool);
|
||||
hostClassIndex = input.readUnsignedShort();
|
||||
public NestHost(final NestHost c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getHostClassIndex(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitNestHost(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final NestHost c = (NestHost) clone();
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps NestHost attribute to file stream in binary format.
|
||||
@@ -95,12 +101,11 @@ public final class NestHost extends Attribute {
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(hostClassIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return index into constant pool of host class name.
|
||||
*/
|
||||
@@ -108,15 +113,13 @@ public final class NestHost extends Attribute {
|
||||
return hostClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param hostClassIndex the host class index
|
||||
*/
|
||||
public void setHostClassIndex( final int hostClassIndex ) {
|
||||
public void setHostClassIndex(final int hostClassIndex) {
|
||||
this.hostClassIndex = hostClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@@ -124,19 +127,8 @@ public final class NestHost extends Attribute {
|
||||
public String toString() {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
buf.append("NestHost: ");
|
||||
final String class_name = super.getConstantPool().getConstantString(hostClassIndex, Const.CONSTANT_Class);
|
||||
buf.append(Utility.compactClassName(class_name, false));
|
||||
final String className = super.getConstantPool().getConstantString(hostClassIndex, Const.CONSTANT_Class);
|
||||
buf.append(Utility.compactClassName(className, false));
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final NestHost c = (NestHost) clone();
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -24,82 +23,95 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and records the classes and interfaces that
|
||||
* are authorized to claim membership in the nest hosted by the current class or interface.
|
||||
* There may be at most one NestMembers attribute in a ClassFile structure.
|
||||
* This class is derived from <em>Attribute</em> and records the classes and interfaces that are authorized to claim
|
||||
* membership in the nest hosted by the current class or interface. There may be at most one NestMembers attribute in a
|
||||
* ClassFile structure.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public final class NestMembers extends Attribute {
|
||||
|
||||
private int[] classes;
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
NestMembers(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (int[]) null, constantPool);
|
||||
final int classCount = input.readUnsignedShort();
|
||||
classes = new int[classCount];
|
||||
for (int i = 0; i < classCount; i++) {
|
||||
classes[i] = input.readUnsignedShort();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param classes Table of indices in constant pool
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public NestMembers(final int nameIndex, final int length, final int[] classes, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool);
|
||||
this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY;
|
||||
Args.requireU2(this.classes.length, "classes.length");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public NestMembers(final NestMembers c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getClasses(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param classes Table of indices in constant pool
|
||||
* @param constant_pool Array of constants
|
||||
*/
|
||||
public NestMembers(final int name_index, final int length, final int[] classes,
|
||||
final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_NEST_MEMBERS, name_index, length, constant_pool);
|
||||
this.classes = classes != null ? classes : new int[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* @param name_index Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
*/
|
||||
NestMembers(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
this(name_index, length, (int[]) null, constant_pool);
|
||||
final int number_of_classes = input.readUnsignedShort();
|
||||
classes = new int[number_of_classes];
|
||||
for (int i = 0; i < number_of_classes; i++) {
|
||||
classes[i] = input.readUnsignedShort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitNestMembers(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final NestMembers c = (NestMembers) clone();
|
||||
if (classes.length > 0) {
|
||||
c.classes = classes.clone();
|
||||
}
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump NestMembers attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(classes.length);
|
||||
for (final int index : classes) {
|
||||
@@ -107,7 +119,6 @@ public final class NestMembers extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array of indices into constant pool of class names.
|
||||
*/
|
||||
@@ -115,36 +126,28 @@ public final class NestMembers extends Attribute {
|
||||
return classes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Length of classes table.
|
||||
*/
|
||||
public int getNumberClasses() {
|
||||
return classes == null ? 0 : classes.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string array of class names
|
||||
*/
|
||||
public String[] getClassNames() {
|
||||
final String[] names = new String[classes.length];
|
||||
for (int i = 0; i < classes.length; i++) {
|
||||
names[i] = super.getConstantPool().getConstantString(classes[i],
|
||||
Const.CONSTANT_Class).replace('/', '.');
|
||||
}
|
||||
Arrays.setAll(names, i -> Utility.pathToPackage(super.getConstantPool().getConstantString(classes[i], Const.CONSTANT_Class)));
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param classes the list of class indexes
|
||||
* Also redefines number_of_classes according to table length.
|
||||
* @return Length of classes table.
|
||||
*/
|
||||
public void setClasses( final int[] classes ) {
|
||||
this.classes = classes != null ? classes : new int[0];
|
||||
public int getNumberClasses() {
|
||||
return classes.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classes the list of class indexes Also redefines number_of_classes according to table length.
|
||||
*/
|
||||
public void setClasses(final int[] classes) {
|
||||
this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation, i.e., a list of classes.
|
||||
@@ -156,25 +159,9 @@ public final class NestMembers extends Attribute {
|
||||
buf.append(classes.length);
|
||||
buf.append("):\n");
|
||||
for (final int index : classes) {
|
||||
final String class_name = super.getConstantPool().getConstantString(index, Const.CONSTANT_Class);
|
||||
buf.append(" ").append(Utility.compactClassName(class_name, false)).append("\n");
|
||||
final String className = super.getConstantPool().getConstantString(index, Const.CONSTANT_Class);
|
||||
buf.append(" ").append(Utility.compactClassName(className, false)).append("\n");
|
||||
}
|
||||
return buf.substring(0, buf.length()-1); // remove the last newline
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final NestMembers c = (NestMembers) clone();
|
||||
if (classes != null) {
|
||||
c.classes = new int[classes.length];
|
||||
System.arraycopy(classes, 0, c.classes, 0,
|
||||
classes.length);
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
return buf.substring(0, buf.length() - 1); // remove the last newline
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,8 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
/**
|
||||
* Denote class to have an accept method();
|
||||
*
|
||||
*/
|
||||
public interface Node {
|
||||
|
||||
void accept( Visitor obj );
|
||||
void accept(Visitor obj);
|
||||
}
|
||||
|
||||
@@ -28,83 +28,83 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and represents a reference
|
||||
* to a PMG attribute.
|
||||
* This class is derived from <em>Attribute</em> and represents a reference to a PMG attribute.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class PMGClass extends Attribute {
|
||||
|
||||
private int pmgClassIndex;
|
||||
private int pmgIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
*/
|
||||
public PMGClass(final PMGClass pgmClass) {
|
||||
this(pgmClass.getNameIndex(), pgmClass.getLength(), pgmClass.getPMGIndex(), pgmClass.getPMGClassIndex(),
|
||||
pgmClass.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
*
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
PMGClass(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, input.readUnsignedShort(), input.readUnsignedShort(), constant_pool);
|
||||
PMGClass(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, input.readUnsignedShort(), input.readUnsignedShort(), constantPool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param pmgIndex index in constant pool for source file name
|
||||
* @param pmgClassIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public PMGClass(final int name_index, final int length, final int pmgIndex, final int pmgClassIndex,
|
||||
final ConstantPool constantPool) {
|
||||
super(Const.ATTR_PMG, name_index, length, constantPool);
|
||||
public PMGClass(final int nameIndex, final int length, final int pmgIndex, final int pmgClassIndex, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_PMG, nameIndex, length, constantPool);
|
||||
this.pmgIndex = pmgIndex;
|
||||
this.pmgClassIndex = pmgClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param pgmClass Source to copy.
|
||||
*/
|
||||
public PMGClass(final PMGClass pgmClass) {
|
||||
this(pgmClass.getNameIndex(), pgmClass.getLength(), pgmClass.getPMGIndex(), pgmClass.getPMGClassIndex(), pgmClass.getConstantPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
println("Visiting non-standard PMGClass object");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump source file attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(pmgIndex);
|
||||
file.writeShort(pmgClassIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of source file name.
|
||||
*/
|
||||
@@ -112,15 +112,13 @@ public final class PMGClass extends Attribute {
|
||||
return pmgClassIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param pmgClassIndex
|
||||
* @return PMG class name.
|
||||
*/
|
||||
public void setPMGClassIndex( final int pmgClassIndex ) {
|
||||
this.pmgClassIndex = pmgClassIndex;
|
||||
public String getPMGClassName() {
|
||||
return super.getConstantPool().getConstantUtf8(pmgClassIndex).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of source file name.
|
||||
*/
|
||||
@@ -128,34 +126,26 @@ public final class PMGClass extends Attribute {
|
||||
return pmgIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param pmgIndex
|
||||
*/
|
||||
public void setPMGIndex( final int pmgIndex ) {
|
||||
this.pmgIndex = pmgIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return PMG name.
|
||||
*/
|
||||
public String getPMGName() {
|
||||
final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(pmgIndex,
|
||||
Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
return super.getConstantPool().getConstantUtf8(pmgIndex).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return PMG class name.
|
||||
* @param pmgClassIndex
|
||||
*/
|
||||
public String getPMGClassName() {
|
||||
final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(pmgClassIndex,
|
||||
Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
public void setPMGClassIndex(final int pmgClassIndex) {
|
||||
this.pmgClassIndex = pmgClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pmgIndex
|
||||
*/
|
||||
public void setPMGIndex(final int pmgIndex) {
|
||||
this.pmgIndex = pmgIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
@@ -164,13 +154,4 @@ public final class PMGClass extends Attribute {
|
||||
public String toString() {
|
||||
return "PMGClass(" + getPMGName() + ", " + getPMGClassName() + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,44 +35,48 @@ import java.util.List;
|
||||
*/
|
||||
public class ParameterAnnotationEntry implements Node {
|
||||
|
||||
private final AnnotationEntry[] annotationTable;
|
||||
static final ParameterAnnotationEntry[] EMPTY_ARRAY = {};
|
||||
|
||||
public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) {
|
||||
// Find attributes that contain parameter annotation data
|
||||
final List<ParameterAnnotationEntry> accumulatedAnnotations = new ArrayList<>(attrs.length);
|
||||
for (final Attribute attribute : attrs) {
|
||||
if (attribute instanceof ParameterAnnotations) {
|
||||
final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations) attribute;
|
||||
Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries());
|
||||
}
|
||||
}
|
||||
return accumulatedAnnotations.toArray(ParameterAnnotationEntry.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
private final AnnotationEntry[] annotationTable;
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param input Input stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ParameterAnnotationEntry(final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
final int annotation_table_length = input.readUnsignedShort();
|
||||
annotationTable = new AnnotationEntry[annotation_table_length];
|
||||
for (int i = 0; i < annotation_table_length; i++) {
|
||||
ParameterAnnotationEntry(final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
final int annotationTableLength = input.readUnsignedShort();
|
||||
annotationTable = new AnnotationEntry[annotationTableLength];
|
||||
for (int i = 0; i < annotationTableLength; i++) {
|
||||
// TODO isRuntimeVisible
|
||||
annotationTable[i] = AnnotationEntry.read(input, constant_pool, false);
|
||||
annotationTable[i] = AnnotationEntry.read(input, constantPool, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitParameterAnnotationEntry(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the array of annotation entries in this annotation
|
||||
*/
|
||||
public AnnotationEntry[] getAnnotationEntries() {
|
||||
return annotationTable;
|
||||
}
|
||||
|
||||
public void dump(final DataOutputStream dos) throws IOException {
|
||||
dos.writeShort(annotationTable.length);
|
||||
for (final AnnotationEntry entry : annotationTable) {
|
||||
@@ -80,15 +84,10 @@ public class ParameterAnnotationEntry implements Node {
|
||||
}
|
||||
}
|
||||
|
||||
public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) {
|
||||
// Find attributes that contain parameter annotation data
|
||||
final List<ParameterAnnotationEntry> accumulatedAnnotations = new ArrayList<>(attrs.length);
|
||||
for (final Attribute attribute : attrs) {
|
||||
if (attribute instanceof ParameterAnnotations) {
|
||||
final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations)attribute;
|
||||
Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries());
|
||||
}
|
||||
}
|
||||
return accumulatedAnnotations.toArray(new ParameterAnnotationEntry[accumulatedAnnotations.size()]);
|
||||
}
|
||||
/**
|
||||
* returns the array of annotation entries in this annotation
|
||||
*/
|
||||
public AnnotationEntry[] getAnnotationEntries() {
|
||||
return annotationTable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,36 +24,36 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* base class for parameter annotations
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public abstract class ParameterAnnotations extends Attribute {
|
||||
public abstract class ParameterAnnotations extends Attribute implements Iterable<ParameterAnnotationEntry> {
|
||||
|
||||
/** Table of parameter annotations */
|
||||
private ParameterAnnotationEntry[] parameterAnnotationTable;
|
||||
|
||||
/**
|
||||
* @param parameter_annotation_type the subclass type of the parameter annotation
|
||||
* @param name_index Index pointing to the name <em>Code</em>
|
||||
* @param parameterAnnotationType the subclass type of the parameter annotation
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
ParameterAnnotations(final byte parameter_annotation_type, final int name_index, final int length,
|
||||
final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
this(parameter_annotation_type, name_index, length, (ParameterAnnotationEntry[]) null,
|
||||
constant_pool);
|
||||
final int num_parameters = input.readUnsignedByte();
|
||||
parameterAnnotationTable = new ParameterAnnotationEntry[num_parameters];
|
||||
for (int i = 0; i < num_parameters; i++) {
|
||||
parameterAnnotationTable[i] = new ParameterAnnotationEntry(input, constant_pool);
|
||||
ParameterAnnotations(final byte parameterAnnotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
|
||||
throws IOException {
|
||||
this(parameterAnnotationType, nameIndex, length, (ParameterAnnotationEntry[]) null, constantPool);
|
||||
final int numParameters = input.readUnsignedByte();
|
||||
parameterAnnotationTable = new ParameterAnnotationEntry[numParameters];
|
||||
for (int i = 0; i < numParameters; i++) {
|
||||
parameterAnnotationTable[i] = new ParameterAnnotationEntry(input, constantPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param parameterAnnotationType the subclass type of the parameter annotation
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
@@ -62,51 +62,32 @@ public abstract class ParameterAnnotations extends Attribute {
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public ParameterAnnotations(final byte parameterAnnotationType, final int nameIndex, final int length,
|
||||
final ParameterAnnotationEntry[] parameterAnnotationTable, final ConstantPool constantPool) {
|
||||
final ParameterAnnotationEntry[] parameterAnnotationTable, final ConstantPool constantPool) {
|
||||
super(parameterAnnotationType, nameIndex, length, constantPool);
|
||||
this.parameterAnnotationTable = parameterAnnotationTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitParameterAnnotation(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param parameterAnnotationTable the entries to set in this parameter annotation
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable ) {
|
||||
this.parameterAnnotationTable = parameterAnnotationTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the parameter annotation entry table
|
||||
*/
|
||||
public final ParameterAnnotationEntry[] getParameterAnnotationTable() {
|
||||
return parameterAnnotationTable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns the array of parameter annotation entries in this parameter annotation
|
||||
*/
|
||||
public ParameterAnnotationEntry[] getParameterAnnotationEntries() {
|
||||
return parameterAnnotationTable;
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(final DataOutputStream dos) throws IOException
|
||||
{
|
||||
public void dump(final DataOutputStream dos) throws IOException {
|
||||
super.dump(dos);
|
||||
dos.writeByte(parameterAnnotationTable.length);
|
||||
|
||||
@@ -117,10 +98,28 @@ public abstract class ParameterAnnotations extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
* returns the array of parameter annotation entries in this parameter annotation
|
||||
*/
|
||||
public ParameterAnnotationEntry[] getParameterAnnotationEntries() {
|
||||
return parameterAnnotationTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the parameter annotation entry table
|
||||
*/
|
||||
public final ParameterAnnotationEntry[] getParameterAnnotationTable() {
|
||||
return parameterAnnotationTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool constant_pool ) {
|
||||
return (Attribute) clone();
|
||||
public Iterator<ParameterAnnotationEntry> iterator() {
|
||||
return Stream.of(parameterAnnotationTable).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parameterAnnotationTable the entries to set in this parameter annotation
|
||||
*/
|
||||
public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable) {
|
||||
this.parameterAnnotationTable = parameterAnnotationTable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,41 +28,33 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* represents an annotation that is represented in the class file but is not
|
||||
* provided to the JVM.
|
||||
* represents an annotation that is represented in the class file but is not provided to the JVM.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class RuntimeInvisibleAnnotations extends Annotations
|
||||
{
|
||||
public class RuntimeInvisibleAnnotations extends Annotations {
|
||||
|
||||
/**
|
||||
* @param name_index
|
||||
* Index pointing to the name <em>Code</em>
|
||||
* @param length
|
||||
* Content length in bytes
|
||||
* @param input
|
||||
* Input stream
|
||||
* @param constant_pool
|
||||
* Array of constants
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
||||
*/
|
||||
public RuntimeInvisibleAnnotations(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException
|
||||
{
|
||||
super(Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS, name_index, length, input, constant_pool, false);
|
||||
public RuntimeInvisibleAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
super(Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS, nameIndex, length, input, constantPool, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constant_pool)
|
||||
{
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void dump(final DataOutputStream dos) throws IOException
|
||||
{
|
||||
public final void dump(final DataOutputStream dos) throws IOException {
|
||||
super.dump(dos);
|
||||
writeAnnotations(dos);
|
||||
}
|
||||
|
||||
@@ -27,21 +27,21 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* Represents a parameter annotation that is represented in the class file
|
||||
* but is not provided to the JVM.
|
||||
* Represents a parameter annotation that is represented in the class file but is not provided to the JVM.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations {
|
||||
|
||||
/**
|
||||
* @param name_index Index pointing to the name <em>Code</em>
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
||||
*/
|
||||
public RuntimeInvisibleParameterAnnotations(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
super(Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, name_index, length, input, constant_pool);
|
||||
public RuntimeInvisibleParameterAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
|
||||
throws IOException {
|
||||
super(Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, nameIndex, length, input, constantPool);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,40 +28,33 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* represents an annotation that is represented in the class file and is
|
||||
* provided to the JVM.
|
||||
* represents an annotation that is represented in the class file and is provided to the JVM.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class RuntimeVisibleAnnotations extends Annotations
|
||||
{
|
||||
public class RuntimeVisibleAnnotations extends Annotations {
|
||||
|
||||
/**
|
||||
* @param name_index
|
||||
* Index pointing to the name <em>Code</em>
|
||||
* @param length
|
||||
* Content length in bytes
|
||||
* @param input
|
||||
* Input stream
|
||||
* @param constant_pool
|
||||
* Array of constants
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
||||
*/
|
||||
public RuntimeVisibleAnnotations(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException
|
||||
{
|
||||
super(Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, name_index, length, input, constant_pool, true);
|
||||
public RuntimeVisibleAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
super(Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, nameIndex, length, input, constantPool, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constant_pool)
|
||||
{
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void dump(final DataOutputStream dos) throws IOException
|
||||
{
|
||||
public final void dump(final DataOutputStream dos) throws IOException {
|
||||
super.dump(dos);
|
||||
writeAnnotations(dos);
|
||||
}
|
||||
|
||||
@@ -27,21 +27,21 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* Represents a parameter annotation that is represented in the class file
|
||||
* and is provided to the JVM.
|
||||
* Represents a parameter annotation that is represented in the class file and is provided to the JVM.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations {
|
||||
|
||||
/**
|
||||
* @param name_index Index pointing to the name <em>Code</em>
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
||||
*/
|
||||
public RuntimeVisibleParameterAnnotations(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
super(Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, input, constant_pool);
|
||||
public RuntimeVisibleParameterAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
|
||||
throws IOException {
|
||||
super(Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, nameIndex, length, input, constantPool);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,122 +25,32 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and represents a reference
|
||||
* to a GJ attribute.
|
||||
* This class is derived from <em>Attribute</em> and represents a reference to a GJ attribute.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class Signature extends Attribute {
|
||||
|
||||
private int signatureIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
*/
|
||||
public Signature(final Signature c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
*/
|
||||
Signature(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, input.readUnsignedShort(), constant_pool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param signatureIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param constant_pool Array of constants
|
||||
*/
|
||||
public Signature(final int name_index, final int length, final int signatureIndex, final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_SIGNATURE, name_index, length, constant_pool);
|
||||
this.signatureIndex = signatureIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
//System.err.println("Visiting non-standard Signature object");
|
||||
v.visitSignature(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump source file attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(signatureIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of source file name.
|
||||
*/
|
||||
public int getSignatureIndex() {
|
||||
return signatureIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param signatureIndex the index info the constant pool of this signature
|
||||
*/
|
||||
public void setSignatureIndex( final int signatureIndex ) {
|
||||
this.signatureIndex = signatureIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return GJ signature.
|
||||
*/
|
||||
public String getSignature() {
|
||||
final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(signatureIndex,
|
||||
Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends ByteArrayInputStream to make 'unreading' chars possible.
|
||||
*/
|
||||
private static final class MyByteArrayInputStream extends ByteArrayInputStream {
|
||||
|
||||
MyByteArrayInputStream(final String data) {
|
||||
super(data.getBytes());
|
||||
super(data.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
|
||||
String getData() {
|
||||
return new String(buf);
|
||||
return new String(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
|
||||
void unread() {
|
||||
if (pos > 0) {
|
||||
pos--;
|
||||
@@ -148,19 +58,59 @@ public final class Signature extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean identStart( final int ch ) {
|
||||
private static boolean identStart(final int ch) {
|
||||
return ch == 'T' || ch == 'L';
|
||||
}
|
||||
|
||||
// @since 6.0 is no longer final
|
||||
public static boolean isActualParameterList(final String s) {
|
||||
return s.startsWith("L") && s.endsWith(">;");
|
||||
}
|
||||
|
||||
private static void matchIdent( final MyByteArrayInputStream in, final StringBuilder buf ) {
|
||||
// @since 6.0 is no longer final
|
||||
public static boolean isFormalParameterList(final String s) {
|
||||
return s.startsWith("<") && s.indexOf(':') > 0;
|
||||
}
|
||||
|
||||
private static void matchGJIdent(final MyByteArrayInputStream in, final StringBuilder buf) {
|
||||
int ch;
|
||||
matchIdent(in, buf);
|
||||
ch = in.read();
|
||||
if (ch == '<' || ch == '(') { // Parameterized or method
|
||||
// System.out.println("Enter <");
|
||||
buf.append((char) ch);
|
||||
matchGJIdent(in, buf);
|
||||
while ((ch = in.read()) != '>' && ch != ')') { // List of parameters
|
||||
if (ch == -1) {
|
||||
throw new IllegalArgumentException("Illegal signature: " + in.getData() + " reaching EOF");
|
||||
}
|
||||
// System.out.println("Still no >");
|
||||
buf.append(", ");
|
||||
in.unread();
|
||||
matchGJIdent(in, buf); // Recursive call
|
||||
}
|
||||
// System.out.println("Exit >");
|
||||
buf.append((char) ch);
|
||||
} else {
|
||||
in.unread();
|
||||
}
|
||||
ch = in.read();
|
||||
if (identStart(ch)) {
|
||||
in.unread();
|
||||
matchGJIdent(in, buf);
|
||||
} else if (ch == ')') {
|
||||
in.unread();
|
||||
} else if (ch != ';') {
|
||||
throw new IllegalArgumentException("Illegal signature: " + in.getData() + " read " + (char) ch);
|
||||
}
|
||||
}
|
||||
|
||||
private static void matchIdent(final MyByteArrayInputStream in, final StringBuilder buf) {
|
||||
int ch;
|
||||
if ((ch = in.read()) == -1) {
|
||||
throw new IllegalArgumentException("Illegal signature: " + in.getData()
|
||||
+ " no ident, reaching EOF");
|
||||
throw new IllegalArgumentException("Illegal signature: " + in.getData() + " no ident, reaching EOF");
|
||||
}
|
||||
//System.out.println("return from ident:" + (char)ch);
|
||||
// System.out.println("return from ident:" + (char)ch);
|
||||
if (!identStart(ch)) {
|
||||
final StringBuilder buf2 = new StringBuilder();
|
||||
int count = 1;
|
||||
@@ -170,11 +120,15 @@ public final class Signature extends Attribute {
|
||||
ch = in.read();
|
||||
}
|
||||
if (ch == ':') { // Ok, formal parameter
|
||||
in.skip("Ljava/lang/Object".length());
|
||||
final int skipExpected = "Ljava/lang/Object".length();
|
||||
final long skipActual = in.skip(skipExpected);
|
||||
if (skipActual != skipExpected) {
|
||||
throw new IllegalStateException(String.format("Unexpected skip: expected=%,d, actual=%,d", skipExpected, skipActual));
|
||||
}
|
||||
buf.append(buf2);
|
||||
ch = in.read();
|
||||
in.unread();
|
||||
//System.out.println("so far:" + buf2 + ":next:" +(char)ch);
|
||||
// System.out.println("so far:" + buf2 + ":next:" +(char)ch);
|
||||
} else {
|
||||
for (int i = 0; i < count; i++) {
|
||||
in.unread();
|
||||
@@ -187,87 +141,118 @@ public final class Signature extends Attribute {
|
||||
do {
|
||||
buf2.append((char) ch);
|
||||
ch = in.read();
|
||||
//System.out.println("within ident:"+ (char)ch);
|
||||
} while ((ch != -1) && (Character.isJavaIdentifierPart((char) ch) || (ch == '/')));
|
||||
buf.append(buf2.toString().replace('/', '.'));
|
||||
//System.out.println("regular return ident:"+ (char)ch + ":" + buf2);
|
||||
// System.out.println("within ident:"+ (char)ch);
|
||||
} while (ch != -1 && (Character.isJavaIdentifierPart((char) ch) || ch == '/'));
|
||||
buf.append(Utility.pathToPackage(buf2.toString()));
|
||||
// System.out.println("regular return ident:"+ (char)ch + ":" + buf2);
|
||||
if (ch != -1) {
|
||||
in.unread();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void matchGJIdent( final MyByteArrayInputStream in, final StringBuilder buf ) {
|
||||
int ch;
|
||||
matchIdent(in, buf);
|
||||
ch = in.read();
|
||||
if ((ch == '<') || ch == '(') { // Parameterized or method
|
||||
//System.out.println("Enter <");
|
||||
buf.append((char) ch);
|
||||
matchGJIdent(in, buf);
|
||||
while (((ch = in.read()) != '>') && (ch != ')')) { // List of parameters
|
||||
if (ch == -1) {
|
||||
throw new IllegalArgumentException("Illegal signature: " + in.getData()
|
||||
+ " reaching EOF");
|
||||
}
|
||||
//System.out.println("Still no >");
|
||||
buf.append(", ");
|
||||
in.unread();
|
||||
matchGJIdent(in, buf); // Recursive call
|
||||
}
|
||||
//System.out.println("Exit >");
|
||||
buf.append((char) ch);
|
||||
} else {
|
||||
in.unread();
|
||||
}
|
||||
ch = in.read();
|
||||
if (identStart(ch)) {
|
||||
in.unread();
|
||||
matchGJIdent(in, buf);
|
||||
} else if (ch == ')') {
|
||||
in.unread();
|
||||
return;
|
||||
} else if (ch != ';') {
|
||||
throw new IllegalArgumentException("Illegal signature: " + in.getData() + " read " + (char) ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String translate( final String s ) {
|
||||
//System.out.println("Sig:" + s);
|
||||
public static String translate(final String s) {
|
||||
// System.out.println("Sig:" + s);
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
matchGJIdent(new MyByteArrayInputStream(s), buf);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private int signatureIndex;
|
||||
|
||||
// @since 6.0 is no longer final
|
||||
public static boolean isFormalParameterList( final String s ) {
|
||||
return s.startsWith("<") && (s.indexOf(':') > 0);
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
Signature(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, input.readUnsignedShort(), constantPool);
|
||||
}
|
||||
|
||||
|
||||
// @since 6.0 is no longer final
|
||||
public static boolean isActualParameterList( final String s ) {
|
||||
return s.startsWith("L") && s.endsWith(">;");
|
||||
/**
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param signatureIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public Signature(final int nameIndex, final int length, final int signatureIndex, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_SIGNATURE, nameIndex, Args.require(length, 2, "Signature length attribute"), constantPool);
|
||||
this.signatureIndex = signatureIndex;
|
||||
// validate:
|
||||
Objects.requireNonNull(constantPool.getConstantUtf8(signatureIndex), "constantPool.getConstantUtf8(signatureIndex)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public Signature(final Signature c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept(final Visitor v) {
|
||||
// System.err.println("Visiting non-standard Signature object");
|
||||
v.visitSignature(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump source file attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(signatureIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return GJ signature.
|
||||
*/
|
||||
public String getSignature() {
|
||||
return super.getConstantPool().getConstantUtf8(signatureIndex).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of source file name.
|
||||
*/
|
||||
public int getSignatureIndex() {
|
||||
return signatureIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param signatureIndex the index info the constant pool of this signature
|
||||
*/
|
||||
public void setSignatureIndex(final int signatureIndex) {
|
||||
this.signatureIndex = signatureIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
final String s = getSignature();
|
||||
return "Signature: " + s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
return (Attribute) clone();
|
||||
return "Signature: " + getSignature();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,188 +29,19 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
public class SimpleElementValue extends ElementValue
|
||||
{
|
||||
public class SimpleElementValue extends ElementValue {
|
||||
private int index;
|
||||
|
||||
public SimpleElementValue(final int type, final int index, final ConstantPool cpool)
|
||||
{
|
||||
public SimpleElementValue(final int type, final int index, final ConstantPool cpool) {
|
||||
super(type, cpool);
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Value entry index in the cpool
|
||||
*/
|
||||
public int getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(final int index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getValueString()
|
||||
{
|
||||
if (super.getType() != STRING) {
|
||||
throw new IllegalStateException(
|
||||
"Dont call getValueString() on a non STRING ElementValue");
|
||||
}
|
||||
final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(getIndex(),
|
||||
Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
}
|
||||
|
||||
public int getValueInt()
|
||||
{
|
||||
if (super.getType() != PRIMITIVE_INT) {
|
||||
throw new IllegalStateException(
|
||||
"Dont call getValueString() on a non STRING ElementValue");
|
||||
}
|
||||
final ConstantInteger c = (ConstantInteger) super.getConstantPool().getConstant(getIndex(),
|
||||
Const.CONSTANT_Integer);
|
||||
return c.getBytes();
|
||||
}
|
||||
|
||||
public byte getValueByte()
|
||||
{
|
||||
if (super.getType() != PRIMITIVE_BYTE) {
|
||||
throw new IllegalStateException(
|
||||
"Dont call getValueByte() on a non BYTE ElementValue");
|
||||
}
|
||||
final ConstantInteger c = (ConstantInteger) super.getConstantPool().getConstant(getIndex(),
|
||||
Const.CONSTANT_Integer);
|
||||
return (byte) c.getBytes();
|
||||
}
|
||||
|
||||
public char getValueChar()
|
||||
{
|
||||
if (super.getType() != PRIMITIVE_CHAR) {
|
||||
throw new IllegalStateException(
|
||||
"Dont call getValueChar() on a non CHAR ElementValue");
|
||||
}
|
||||
final ConstantInteger c = (ConstantInteger) super.getConstantPool().getConstant(getIndex(),
|
||||
Const.CONSTANT_Integer);
|
||||
return (char) c.getBytes();
|
||||
}
|
||||
|
||||
public long getValueLong()
|
||||
{
|
||||
if (super.getType() != PRIMITIVE_LONG) {
|
||||
throw new IllegalStateException(
|
||||
"Dont call getValueLong() on a non LONG ElementValue");
|
||||
}
|
||||
final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex());
|
||||
return j.getBytes();
|
||||
}
|
||||
|
||||
public float getValueFloat()
|
||||
{
|
||||
if (super.getType() != PRIMITIVE_FLOAT) {
|
||||
throw new IllegalStateException(
|
||||
"Dont call getValueFloat() on a non FLOAT ElementValue");
|
||||
}
|
||||
final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex());
|
||||
return f.getBytes();
|
||||
}
|
||||
|
||||
public double getValueDouble()
|
||||
{
|
||||
if (super.getType() != PRIMITIVE_DOUBLE) {
|
||||
throw new IllegalStateException(
|
||||
"Dont call getValueDouble() on a non DOUBLE ElementValue");
|
||||
}
|
||||
final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex());
|
||||
return d.getBytes();
|
||||
}
|
||||
|
||||
public boolean getValueBoolean()
|
||||
{
|
||||
if (super.getType() != PRIMITIVE_BOOLEAN) {
|
||||
throw new IllegalStateException(
|
||||
"Dont call getValueBoolean() on a non BOOLEAN ElementValue");
|
||||
}
|
||||
final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
|
||||
return bo.getBytes() != 0;
|
||||
}
|
||||
|
||||
public short getValueShort()
|
||||
{
|
||||
if (super.getType() != PRIMITIVE_SHORT) {
|
||||
throw new IllegalStateException(
|
||||
"Dont call getValueShort() on a non SHORT ElementValue");
|
||||
}
|
||||
final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
|
||||
return (short) s.getBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return stringifyValue();
|
||||
}
|
||||
|
||||
// Whatever kind of value it is, return it as a string
|
||||
@Override
|
||||
public String stringifyValue()
|
||||
{
|
||||
final ConstantPool cpool = super.getConstantPool();
|
||||
final int _type = super.getType();
|
||||
switch (_type)
|
||||
{
|
||||
case PRIMITIVE_INT:
|
||||
final ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(),
|
||||
Const.CONSTANT_Integer);
|
||||
return Integer.toString(c.getBytes());
|
||||
case PRIMITIVE_LONG:
|
||||
final ConstantLong j = (ConstantLong) cpool.getConstant(getIndex(),
|
||||
Const.CONSTANT_Long);
|
||||
return Long.toString(j.getBytes());
|
||||
case PRIMITIVE_DOUBLE:
|
||||
final ConstantDouble d = (ConstantDouble) cpool.getConstant(getIndex(),
|
||||
Const.CONSTANT_Double);
|
||||
return Double.toString(d.getBytes());
|
||||
case PRIMITIVE_FLOAT:
|
||||
final ConstantFloat f = (ConstantFloat) cpool.getConstant(getIndex(),
|
||||
Const.CONSTANT_Float);
|
||||
return Float.toString(f.getBytes());
|
||||
case PRIMITIVE_SHORT:
|
||||
final ConstantInteger s = (ConstantInteger) cpool.getConstant(getIndex(),
|
||||
Const.CONSTANT_Integer);
|
||||
return Integer.toString(s.getBytes());
|
||||
case PRIMITIVE_BYTE:
|
||||
final ConstantInteger b = (ConstantInteger) cpool.getConstant(getIndex(),
|
||||
Const.CONSTANT_Integer);
|
||||
return Integer.toString(b.getBytes());
|
||||
case PRIMITIVE_CHAR:
|
||||
final ConstantInteger ch = (ConstantInteger) cpool.getConstant(
|
||||
getIndex(), Const.CONSTANT_Integer);
|
||||
return String.valueOf((char)ch.getBytes());
|
||||
case PRIMITIVE_BOOLEAN:
|
||||
final ConstantInteger bo = (ConstantInteger) cpool.getConstant(
|
||||
getIndex(), Const.CONSTANT_Integer);
|
||||
if (bo.getBytes() == 0) {
|
||||
return "false";
|
||||
}
|
||||
return "true";
|
||||
case STRING:
|
||||
final ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(getIndex(),
|
||||
Const.CONSTANT_Utf8);
|
||||
return cu8.getBytes();
|
||||
default:
|
||||
throw new IllegalStateException("SimpleElementValue class does not know how to stringify type " + _type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(final DataOutputStream dos) throws IOException
|
||||
{
|
||||
final int _type = super.getType();
|
||||
dos.writeByte(_type); // u1 kind of value
|
||||
switch (_type)
|
||||
{
|
||||
public void dump(final DataOutputStream dos) throws IOException {
|
||||
final int type = super.getType();
|
||||
dos.writeByte(type); // u1 kind of value
|
||||
switch (type) {
|
||||
case PRIMITIVE_INT:
|
||||
case PRIMITIVE_BYTE:
|
||||
case PRIMITIVE_CHAR:
|
||||
@@ -223,7 +54,130 @@ public class SimpleElementValue extends ElementValue
|
||||
dos.writeShort(getIndex());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("SimpleElementValue doesnt know how to write out type " + _type);
|
||||
throw new ClassFormatException("SimpleElementValue doesnt know how to write out type " + type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Value entry index in the cpool
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public boolean getValueBoolean() {
|
||||
if (super.getType() != PRIMITIVE_BOOLEAN) {
|
||||
throw new IllegalStateException("Dont call getValueBoolean() on a non BOOLEAN ElementValue");
|
||||
}
|
||||
final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
|
||||
return bo.getBytes() != 0;
|
||||
}
|
||||
|
||||
public byte getValueByte() {
|
||||
if (super.getType() != PRIMITIVE_BYTE) {
|
||||
throw new IllegalStateException("Dont call getValueByte() on a non BYTE ElementValue");
|
||||
}
|
||||
return (byte) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
|
||||
}
|
||||
|
||||
public char getValueChar() {
|
||||
if (super.getType() != PRIMITIVE_CHAR) {
|
||||
throw new IllegalStateException("Dont call getValueChar() on a non CHAR ElementValue");
|
||||
}
|
||||
return (char) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
|
||||
}
|
||||
|
||||
public double getValueDouble() {
|
||||
if (super.getType() != PRIMITIVE_DOUBLE) {
|
||||
throw new IllegalStateException("Dont call getValueDouble() on a non DOUBLE ElementValue");
|
||||
}
|
||||
final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex());
|
||||
return d.getBytes();
|
||||
}
|
||||
|
||||
public float getValueFloat() {
|
||||
if (super.getType() != PRIMITIVE_FLOAT) {
|
||||
throw new IllegalStateException("Dont call getValueFloat() on a non FLOAT ElementValue");
|
||||
}
|
||||
final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex());
|
||||
return f.getBytes();
|
||||
}
|
||||
|
||||
public int getValueInt() {
|
||||
if (super.getType() != PRIMITIVE_INT) {
|
||||
throw new IllegalStateException("Dont call getValueInt() on a non INT ElementValue");
|
||||
}
|
||||
return super.getConstantPool().getConstantInteger(getIndex()).getBytes();
|
||||
}
|
||||
|
||||
public long getValueLong() {
|
||||
if (super.getType() != PRIMITIVE_LONG) {
|
||||
throw new IllegalStateException("Dont call getValueLong() on a non LONG ElementValue");
|
||||
}
|
||||
final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex());
|
||||
return j.getBytes();
|
||||
}
|
||||
|
||||
public short getValueShort() {
|
||||
if (super.getType() != PRIMITIVE_SHORT) {
|
||||
throw new IllegalStateException("Dont call getValueShort() on a non SHORT ElementValue");
|
||||
}
|
||||
final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
|
||||
return (short) s.getBytes();
|
||||
}
|
||||
|
||||
public String getValueString() {
|
||||
if (super.getType() != STRING) {
|
||||
throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue");
|
||||
}
|
||||
return super.getConstantPool().getConstantUtf8(getIndex()).getBytes();
|
||||
}
|
||||
|
||||
public void setIndex(final int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
// Whatever kind of value it is, return it as a string
|
||||
@Override
|
||||
public String stringifyValue() {
|
||||
final ConstantPool cpool = super.getConstantPool();
|
||||
final int type = super.getType();
|
||||
switch (type) {
|
||||
case PRIMITIVE_INT:
|
||||
return Integer.toString(cpool.getConstantInteger(getIndex()).getBytes());
|
||||
case PRIMITIVE_LONG:
|
||||
final ConstantLong j = cpool.getConstant(getIndex(), Const.CONSTANT_Long, ConstantLong.class);
|
||||
return Long.toString(j.getBytes());
|
||||
case PRIMITIVE_DOUBLE:
|
||||
final ConstantDouble d = cpool.getConstant(getIndex(), Const.CONSTANT_Double, ConstantDouble.class);
|
||||
return Double.toString(d.getBytes());
|
||||
case PRIMITIVE_FLOAT:
|
||||
final ConstantFloat f = cpool.getConstant(getIndex(), Const.CONSTANT_Float, ConstantFloat.class);
|
||||
return Float.toString(f.getBytes());
|
||||
case PRIMITIVE_SHORT:
|
||||
final ConstantInteger s = cpool.getConstantInteger(getIndex());
|
||||
return Integer.toString(s.getBytes());
|
||||
case PRIMITIVE_BYTE:
|
||||
final ConstantInteger b = cpool.getConstantInteger(getIndex());
|
||||
return Integer.toString(b.getBytes());
|
||||
case PRIMITIVE_CHAR:
|
||||
final ConstantInteger ch = cpool.getConstantInteger(getIndex());
|
||||
return String.valueOf((char) ch.getBytes());
|
||||
case PRIMITIVE_BOOLEAN:
|
||||
final ConstantInteger bo = cpool.getConstantInteger(getIndex());
|
||||
if (bo.getBytes() == 0) {
|
||||
return "false";
|
||||
}
|
||||
return "true";
|
||||
case STRING:
|
||||
return cpool.getConstantUtf8(getIndex()).getBytes();
|
||||
default:
|
||||
throw new IllegalStateException("SimpleElementValue class does not know how to stringify type " + type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return stringifyValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,88 +26,87 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and represents a reference
|
||||
* to the source file of this class. At most one SourceFile attribute
|
||||
* should appear per classfile. The intention of this class is that it is
|
||||
* instantiated from the <em>Attribute.readAttribute()</em> method.
|
||||
* This class is derived from <em>Attribute</em> and represents a reference to the source file of this class. At most
|
||||
* one SourceFile attribute should appear per classfile. The intention of this class is that it is instantiated from the
|
||||
* <em>Attribute.readAttribute()</em> method.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class SourceFile extends Attribute {
|
||||
|
||||
private int sourceFileIndex;
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
SourceFile(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, input.readUnsignedShort(), constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8, which should represent the string "SourceFile".
|
||||
* @param length Content length in bytes, the value should be 2.
|
||||
* @param constantPool The constant pool that this attribute is associated with.
|
||||
* @param sourceFileIndex Index in constant pool to CONSTANT_Utf8. This string will be interpreted as the name of the
|
||||
* file from which this class was compiled. It will not be interpreted as indicating the name of the directory
|
||||
* contqining the file or an absolute path; this information has to be supplied the consumer of this attribute -
|
||||
* in many cases, the JVM.
|
||||
*/
|
||||
public SourceFile(final int nameIndex, final int length, final int sourceFileIndex, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_SOURCE_FILE, nameIndex, Args.require(length, 2, "SourceFile length attribute"), constantPool);
|
||||
this.sourceFileIndex = Args.requireU2(sourceFileIndex, 0, constantPool.getLength(), "SourceFile source file index");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public SourceFile(final SourceFile c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getSourceFileIndex(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
*/
|
||||
SourceFile(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, input.readUnsignedShort(), constant_pool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8, which
|
||||
* should represent the string "SourceFile".
|
||||
* @param length Content length in bytes, the value should be 2.
|
||||
* @param constantPool The constant pool that this attribute is
|
||||
* associated with.
|
||||
* @param sourceFileIndex Index in constant pool to CONSTANT_Utf8. This
|
||||
* string will be interpreted as the name of the file from which this
|
||||
* class was compiled. It will not be interpreted as indicating the name
|
||||
* of the directory contqining the file or an absolute path; this
|
||||
* information has to be supplied the consumer of this attribute - in
|
||||
* many cases, the JVM.
|
||||
*/
|
||||
public SourceFile(final int name_index, final int length, final int sourceFileIndex, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_SOURCE_FILE, name_index, length, constantPool);
|
||||
this.sourceFileIndex = sourceFileIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitSourceFile(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump source file attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(sourceFileIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Index in constant pool of source file name.
|
||||
*/
|
||||
@@ -115,24 +114,19 @@ public final class SourceFile extends Attribute {
|
||||
return sourceFileIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param sourceFileIndex
|
||||
*/
|
||||
public void setSourceFileIndex( final int sourceFileIndex ) {
|
||||
this.sourceFileIndex = sourceFileIndex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Source file name.
|
||||
*/
|
||||
public String getSourceFileName() {
|
||||
final ConstantUtf8 c = (ConstantUtf8) super.getConstantPool().getConstant(sourceFileIndex,
|
||||
Const.CONSTANT_Utf8);
|
||||
return c.getBytes();
|
||||
return super.getConstantPool().getConstantUtf8(sourceFileIndex).getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sourceFileIndex
|
||||
*/
|
||||
public void setSourceFileIndex(final int sourceFileIndex) {
|
||||
this.sourceFileIndex = sourceFileIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
@@ -141,13 +135,4 @@ public final class SourceFile extends Attribute {
|
||||
public String toString() {
|
||||
return "SourceFile: " + getSourceFileName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
return (Attribute) clone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,142 +23,144 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class represents a stack map attribute used for
|
||||
* preverification of Java classes for the <a
|
||||
* href="https://www.oracle.com/java/technologies/javameoverview.html">Java Platform, Micro Edition</a>
|
||||
* (Java ME). This attribute is used by the <a
|
||||
* href="https://www.oracle.com/technetwork/java/embedded/javame/java-mobile/kvmwp-150240.pdf">KVM</a>
|
||||
* and contained within the Code attribute of a method. See CLDC specification
|
||||
* 5.3.1.2
|
||||
* This class represents a stack map attribute used for preverification of Java classes for the
|
||||
* <a href="http://java.sun.com/j2me/"> Java 2 Micro Edition</a> (J2ME). This attribute is used by the
|
||||
* <a href="http://java.sun.com/products/cldc/">KVM</a> and contained within the Code attribute of a method. See CLDC
|
||||
* specification 5.3.1.2
|
||||
*
|
||||
* @see Code
|
||||
* @see StackMapEntry
|
||||
* @see StackMapType
|
||||
* <pre>
|
||||
* StackMapTable_attribute {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u2 number_of_entries;
|
||||
* stack_map_frame entries[number_of_entries];
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see Code
|
||||
* @see StackMapEntry
|
||||
* @see StackMapType
|
||||
* @LastModified: Oct 2020
|
||||
*/
|
||||
public final class StackMap extends Attribute {
|
||||
|
||||
private StackMapEntry[] map; // Table of stack map entries
|
||||
|
||||
|
||||
/*
|
||||
* @param name_index Index of name
|
||||
* @param length Content length in bytes
|
||||
* @param map Table of stack map entries
|
||||
* @param constant_pool Array of constants
|
||||
*/
|
||||
public StackMap(final int name_index, final int length, final StackMapEntry[] map, final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_STACK_MAP, name_index, length, constant_pool);
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
private StackMapEntry[] table; // Table of stack map entries
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param name_index Index of name
|
||||
* @param nameIndex Index of name
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* @param dataInput Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
StackMap(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
|
||||
this(name_index, length, (StackMapEntry[]) null, constant_pool);
|
||||
final int map_length = input.readUnsignedShort();
|
||||
map = new StackMapEntry[map_length];
|
||||
for (int i = 0; i < map_length; i++) {
|
||||
map[i] = new StackMapEntry(input, constant_pool);
|
||||
StackMap(final int nameIndex, final int length, final DataInput dataInput, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (StackMapEntry[]) null, constantPool);
|
||||
final int mapLength = dataInput.readUnsignedShort();
|
||||
table = new StackMapEntry[mapLength];
|
||||
for (int i = 0; i < mapLength; i++) {
|
||||
table[i] = new StackMapEntry(dataInput, constantPool);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @param nameIndex Index of name
|
||||
*
|
||||
* @param length Content length in bytes
|
||||
*
|
||||
* @param map Table of stack map entries
|
||||
*
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public StackMap(final int nameIndex, final int length, final StackMapEntry[] table, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_STACK_MAP, nameIndex, length, constantPool);
|
||||
this.table = table != null ? table : StackMapEntry.EMPTY_ARRAY;
|
||||
Args.requireU2(this.table.length, "table.length");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept(final Visitor v) {
|
||||
v.visitStackMap(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final StackMap c = (StackMap) clone();
|
||||
c.table = new StackMapEntry[table.length];
|
||||
Arrays.setAll(c.table, i -> table[i].copy());
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump stack map table attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
file.writeShort(map.length);
|
||||
for (final StackMapEntry entry : map) {
|
||||
file.writeShort(table.length);
|
||||
for (final StackMapEntry entry : table) {
|
||||
entry.dump(file);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMapLength() {
|
||||
return table.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Array of stack map entries
|
||||
*/
|
||||
public StackMapEntry[] getStackMap() {
|
||||
return map;
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param map Array of stack map entries
|
||||
* @param table Array of stack map entries
|
||||
*/
|
||||
public void setStackMap( final StackMapEntry[] map ) {
|
||||
this.map = map;
|
||||
public void setStackMap(final StackMapEntry[] table) {
|
||||
this.table = table != null ? table : StackMapEntry.EMPTY_ARRAY;
|
||||
int len = 2; // Length of 'number_of_entries' field prior to the array of stack maps
|
||||
for (final StackMapEntry element : map) {
|
||||
for (final StackMapEntry element : this.table) {
|
||||
len += element.getMapEntrySize();
|
||||
}
|
||||
setLength(len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder buf = new StringBuilder("StackMap(");
|
||||
for (int i = 0; i < map.length; i++) {
|
||||
buf.append(map[i]);
|
||||
if (i < map.length - 1) {
|
||||
int runningOffset = -1; // no +1 on first entry
|
||||
for (int i = 0; i < table.length; i++) {
|
||||
runningOffset = table[i].getByteCodeOffset() + runningOffset + 1;
|
||||
buf.append(String.format("%n@%03d %s", runningOffset, table[i]));
|
||||
if (i < table.length - 1) {
|
||||
buf.append(", ");
|
||||
}
|
||||
}
|
||||
buf.append(')');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final StackMap c = (StackMap) clone();
|
||||
c.map = new StackMapEntry[map.length];
|
||||
for (int i = 0; i < map.length; i++) {
|
||||
c.map[i] = map[i].copy();
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
v.visitStackMap(this);
|
||||
}
|
||||
|
||||
|
||||
public int getMapLength() {
|
||||
return map == null ? 0 : map.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,18 +24,33 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents a stack map entry recording the types of
|
||||
* local variables and the the of stack items at a given byte code offset.
|
||||
* See CLDC specification 5.3.1.2
|
||||
* This class represents a stack map entry recording the types of local variables and the of stack items at a given
|
||||
* byte code offset. See CLDC specification 5.3.1.2.
|
||||
*
|
||||
* @see StackMap
|
||||
* @see StackMapType
|
||||
* See also https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.4
|
||||
*
|
||||
* <pre>
|
||||
* union stack_map_frame {
|
||||
* same_frame;
|
||||
* same_locals_1_stack_item_frame;
|
||||
* same_locals_1_stack_item_frame_extended;
|
||||
* chop_frame;
|
||||
* same_frame_extended;
|
||||
* append_frame;
|
||||
* full_frame;
|
||||
* }
|
||||
* </pre>
|
||||
* @see StackMap
|
||||
* @see StackMapType
|
||||
*/
|
||||
public final class StackMapEntry implements Node, Cloneable
|
||||
{
|
||||
public final class StackMapEntry implements Node, Cloneable {
|
||||
|
||||
static final StackMapEntry[] EMPTY_ARRAY = {};
|
||||
|
||||
private int frameType;
|
||||
private int byteCodeOffset;
|
||||
@@ -43,53 +58,49 @@ public final class StackMapEntry implements Node, Cloneable
|
||||
private StackMapType[] typesOfStackItems;
|
||||
private ConstantPool constantPool;
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param input Input stream
|
||||
* @throws IOException
|
||||
* @param dataInput Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
StackMapEntry(final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(input.readByte() & 0xFF, -1, null, null, constantPool);
|
||||
StackMapEntry(final DataInput dataInput, final ConstantPool constantPool) throws IOException {
|
||||
this(dataInput.readByte() & 0xFF, -1, null, null, constantPool);
|
||||
|
||||
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
||||
byteCodeOffset = frameType - Const.SAME_FRAME;
|
||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME &&
|
||||
frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
byteCodeOffset = frameType - Const.SAME_LOCALS_1_STACK_ITEM_FRAME;
|
||||
typesOfStackItems = new StackMapType[1];
|
||||
typesOfStackItems[0] = new StackMapType(input, constantPool);
|
||||
typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) };
|
||||
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
|
||||
byteCodeOffset = input.readShort();
|
||||
typesOfStackItems = new StackMapType[1];
|
||||
typesOfStackItems[0] = new StackMapType(input, constantPool);
|
||||
byteCodeOffset = dataInput.readUnsignedShort();
|
||||
typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) };
|
||||
} else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
|
||||
byteCodeOffset = input.readShort();
|
||||
byteCodeOffset = dataInput.readUnsignedShort();
|
||||
} else if (frameType == Const.SAME_FRAME_EXTENDED) {
|
||||
byteCodeOffset = input.readShort();
|
||||
byteCodeOffset = dataInput.readUnsignedShort();
|
||||
} else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
|
||||
byteCodeOffset = input.readShort();
|
||||
final int number_of_locals = frameType - 251;
|
||||
typesOfLocals = new StackMapType[number_of_locals];
|
||||
for (int i = 0; i < number_of_locals; i++) {
|
||||
typesOfLocals[i] = new StackMapType(input, constantPool);
|
||||
byteCodeOffset = dataInput.readUnsignedShort();
|
||||
final int numberOfLocals = frameType - 251;
|
||||
typesOfLocals = new StackMapType[numberOfLocals];
|
||||
for (int i = 0; i < numberOfLocals; i++) {
|
||||
typesOfLocals[i] = new StackMapType(dataInput, constantPool);
|
||||
}
|
||||
} else if (frameType == Const.FULL_FRAME) {
|
||||
byteCodeOffset = input.readShort();
|
||||
final int number_of_locals = input.readShort();
|
||||
typesOfLocals = new StackMapType[number_of_locals];
|
||||
for (int i = 0; i < number_of_locals; i++) {
|
||||
typesOfLocals[i] = new StackMapType(input, constantPool);
|
||||
byteCodeOffset = dataInput.readUnsignedShort();
|
||||
final int numberOfLocals = dataInput.readUnsignedShort();
|
||||
typesOfLocals = new StackMapType[numberOfLocals];
|
||||
for (int i = 0; i < numberOfLocals; i++) {
|
||||
typesOfLocals[i] = new StackMapType(dataInput, constantPool);
|
||||
}
|
||||
final int number_of_stack_items = input.readShort();
|
||||
typesOfStackItems = new StackMapType[number_of_stack_items];
|
||||
for (int i = 0; i < number_of_stack_items; i++) {
|
||||
typesOfStackItems[i] = new StackMapType(input, constantPool);
|
||||
final int numberOfStackItems = dataInput.readUnsignedShort();
|
||||
typesOfStackItems = new StackMapType[numberOfStackItems];
|
||||
for (int i = 0; i < numberOfStackItems; i++) {
|
||||
typesOfStackItems[i] = new StackMapType(dataInput, constantPool);
|
||||
}
|
||||
} else {
|
||||
/* Can't happen */
|
||||
throw new ClassFormatException ("Invalid frame type found while parsing stack map table: " + frameType);
|
||||
throw new ClassFormatException("Invalid frame type found while parsing stack map table: " + frameType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,17 +113,21 @@ public final class StackMapEntry implements Node, Cloneable
|
||||
* @param numberOfStackItems NOT USED
|
||||
* @param typesOfStackItems array ot {@link StackMapType}s of stack items
|
||||
* @param constantPool the constant pool
|
||||
* @deprecated Since 6.0, use {@link #StackMapEntry(int, int, StackMapType[], StackMapType[], ConstantPool)}
|
||||
* instead
|
||||
* @deprecated Since 6.0, use {@link #StackMapEntry(int, int, StackMapType[], StackMapType[], ConstantPool)} instead
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public StackMapEntry(final int byteCodeOffset, final int numberOfLocals,
|
||||
final StackMapType[] typesOfLocals, final int numberOfStackItems,
|
||||
final StackMapType[] typesOfStackItems, final ConstantPool constantPool) {
|
||||
public StackMapEntry(final int byteCodeOffset, final int numberOfLocals, final StackMapType[] typesOfLocals, final int numberOfStackItems,
|
||||
final StackMapType[] typesOfStackItems, final ConstantPool constantPool) {
|
||||
this.byteCodeOffset = byteCodeOffset;
|
||||
this.typesOfLocals = typesOfLocals != null ? typesOfLocals : new StackMapType[0];
|
||||
this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : new StackMapType[0];
|
||||
this.typesOfLocals = typesOfLocals != null ? typesOfLocals : StackMapType.EMPTY_ARRAY;
|
||||
this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : StackMapType.EMPTY_ARRAY;
|
||||
this.constantPool = constantPool;
|
||||
if (numberOfLocals < 0) {
|
||||
throw new IllegalArgumentException("numberOfLocals < 0");
|
||||
}
|
||||
if (numberOfStackItems < 0) {
|
||||
throw new IllegalArgumentException("numberOfStackItems < 0");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,29 +139,53 @@ public final class StackMapEntry implements Node, Cloneable
|
||||
* @param typesOfStackItems array ot {@link StackMapType}s of stack items
|
||||
* @param constantPool the constant pool
|
||||
*/
|
||||
public StackMapEntry(final int tag, final int byteCodeOffset,
|
||||
final StackMapType[] typesOfLocals,
|
||||
final StackMapType[] typesOfStackItems, final ConstantPool constantPool) {
|
||||
public StackMapEntry(final int tag, final int byteCodeOffset, final StackMapType[] typesOfLocals, final StackMapType[] typesOfStackItems,
|
||||
final ConstantPool constantPool) {
|
||||
this.frameType = tag;
|
||||
this.byteCodeOffset = byteCodeOffset;
|
||||
this.typesOfLocals = typesOfLocals != null ? typesOfLocals : new StackMapType[0];
|
||||
this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : new StackMapType[0];
|
||||
this.typesOfLocals = typesOfLocals != null ? typesOfLocals : StackMapType.EMPTY_ARRAY;
|
||||
this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : StackMapType.EMPTY_ARRAY;
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept(final Visitor v) {
|
||||
v.visitStackMapEntry(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
public StackMapEntry copy() {
|
||||
StackMapEntry e;
|
||||
try {
|
||||
e = (StackMapEntry) clone();
|
||||
} catch (final CloneNotSupportedException ex) {
|
||||
throw new Error("Clone Not Supported");
|
||||
}
|
||||
|
||||
e.typesOfLocals = new StackMapType[typesOfLocals.length];
|
||||
Arrays.setAll(e.typesOfLocals, i -> typesOfLocals[i].copy());
|
||||
e.typesOfStackItems = new StackMapType[typesOfStackItems.length];
|
||||
Arrays.setAll(e.typesOfStackItems, i -> typesOfStackItems[i].copy());
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump stack map entry
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.write(frameType);
|
||||
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
||||
// nothing to be done
|
||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME &&
|
||||
frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
typesOfStackItems[0].dump(file);
|
||||
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
|
||||
file.writeShort(byteCodeOffset);
|
||||
@@ -170,12 +209,154 @@ public final class StackMapEntry implements Node, Cloneable
|
||||
for (final StackMapType type : typesOfStackItems) {
|
||||
type.dump(file);
|
||||
}
|
||||
} else {
|
||||
} else if (!(frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX)) {
|
||||
/* Can't happen */
|
||||
throw new ClassFormatException ("Invalid Stack map table tag: " + frameType);
|
||||
throw new ClassFormatException("Invalid Stack map table tag: " + frameType);
|
||||
}
|
||||
}
|
||||
|
||||
public int getByteCodeOffset() {
|
||||
return byteCodeOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Constant pool used by this object.
|
||||
*/
|
||||
public ConstantPool getConstantPool() {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
public int getFrameType() {
|
||||
return frameType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate stack map entry size
|
||||
*
|
||||
*/
|
||||
int getMapEntrySize() {
|
||||
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
||||
return 1;
|
||||
}
|
||||
if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
return 1 + (typesOfStackItems[0].hasIndex() ? 3 : 1);
|
||||
}
|
||||
if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
|
||||
return 3 + (typesOfStackItems[0].hasIndex() ? 3 : 1);
|
||||
}
|
||||
if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) {
|
||||
return 3;
|
||||
}
|
||||
if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
|
||||
int len = 3;
|
||||
for (final StackMapType typesOfLocal : typesOfLocals) {
|
||||
len += typesOfLocal.hasIndex() ? 3 : 1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
if (frameType != Const.FULL_FRAME) {
|
||||
throw new IllegalStateException("Invalid StackMap frameType: " + frameType);
|
||||
}
|
||||
int len = 7;
|
||||
for (final StackMapType typesOfLocal : typesOfLocals) {
|
||||
len += typesOfLocal.hasIndex() ? 3 : 1;
|
||||
}
|
||||
for (final StackMapType typesOfStackItem : typesOfStackItems) {
|
||||
len += typesOfStackItem.hasIndex() ? 3 : 1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
public int getNumberOfLocals() {
|
||||
return typesOfLocals.length;
|
||||
}
|
||||
|
||||
public int getNumberOfStackItems() {
|
||||
return typesOfStackItems.length;
|
||||
}
|
||||
|
||||
public StackMapType[] getTypesOfLocals() {
|
||||
return typesOfLocals;
|
||||
}
|
||||
|
||||
public StackMapType[] getTypesOfStackItems() {
|
||||
return typesOfStackItems;
|
||||
}
|
||||
|
||||
private boolean invalidFrameType(final int f) {
|
||||
// @formatter:off
|
||||
return f != Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED
|
||||
&& !(f >= Const.CHOP_FRAME && f <= Const.CHOP_FRAME_MAX)
|
||||
&& f != Const.SAME_FRAME_EXTENDED
|
||||
&& !(f >= Const.APPEND_FRAME && f <= Const.APPEND_FRAME_MAX)
|
||||
&& f != Const.FULL_FRAME;
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
public void setByteCodeOffset(final int newOffset) {
|
||||
if (newOffset < 0 || newOffset > 32767) {
|
||||
throw new IllegalArgumentException("Invalid StackMap offset: " + newOffset);
|
||||
}
|
||||
|
||||
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
||||
if (newOffset > Const.SAME_FRAME_MAX) {
|
||||
frameType = Const.SAME_FRAME_EXTENDED;
|
||||
} else {
|
||||
frameType = newOffset;
|
||||
}
|
||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
if (newOffset > Const.SAME_FRAME_MAX) {
|
||||
frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
|
||||
} else {
|
||||
frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME + newOffset;
|
||||
}
|
||||
} else if (invalidFrameType(frameType)) {
|
||||
throw new IllegalStateException("Invalid StackMap frameType: " + frameType);
|
||||
}
|
||||
byteCodeOffset = newOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
*/
|
||||
public void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
public void setFrameType(final int ft) {
|
||||
if (ft >= Const.SAME_FRAME && ft <= Const.SAME_FRAME_MAX) {
|
||||
byteCodeOffset = ft - Const.SAME_FRAME;
|
||||
} else if (ft >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && ft <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
byteCodeOffset = ft - Const.SAME_LOCALS_1_STACK_ITEM_FRAME;
|
||||
} else if (invalidFrameType(ft)) {
|
||||
throw new IllegalArgumentException("Invalid StackMap frameType");
|
||||
}
|
||||
frameType = ft;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated since 6.0
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public void setNumberOfLocals(final int n) { // TODO unused
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated since 6.0
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public void setNumberOfStackItems(final int n) { // TODO unused
|
||||
}
|
||||
|
||||
public void setTypesOfLocals(final StackMapType[] types) {
|
||||
typesOfLocals = types != null ? types : StackMapType.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
public void setTypesOfStackItems(final StackMapType[] types) {
|
||||
typesOfStackItems = types != null ? types : StackMapType.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
@@ -186,17 +367,16 @@ public final class StackMapEntry implements Node, Cloneable
|
||||
buf.append("(");
|
||||
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
||||
buf.append("SAME");
|
||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME &&
|
||||
frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
buf.append("SAME_LOCALS_1_STACK");
|
||||
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
|
||||
buf.append("SAME_LOCALS_1_STACK_EXTENDED");
|
||||
} else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
|
||||
buf.append("CHOP ").append(String.valueOf(251-frameType));
|
||||
buf.append("CHOP ").append(String.valueOf(251 - frameType));
|
||||
} else if (frameType == Const.SAME_FRAME_EXTENDED) {
|
||||
buf.append("SAME_EXTENDED");
|
||||
} else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
|
||||
buf.append("APPEND ").append(String.valueOf(frameType-251));
|
||||
buf.append("APPEND ").append(String.valueOf(frameType - 251));
|
||||
} else if (frameType == Const.FULL_FRAME) {
|
||||
buf.append("FULL");
|
||||
} else {
|
||||
@@ -227,213 +407,13 @@ public final class StackMapEntry implements Node, Cloneable
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate stack map entry size
|
||||
*
|
||||
*/
|
||||
int getMapEntrySize() {
|
||||
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
||||
return 1;
|
||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME &&
|
||||
frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
return 1 + (typesOfStackItems[0].hasIndex() ? 3 : 1);
|
||||
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
|
||||
return 3 + (typesOfStackItems[0].hasIndex() ? 3 : 1);
|
||||
} else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
|
||||
return 3;
|
||||
} else if (frameType == Const.SAME_FRAME_EXTENDED) {
|
||||
return 3;
|
||||
} else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
|
||||
int len = 3;
|
||||
for (final StackMapType types_of_local : typesOfLocals) {
|
||||
len += types_of_local.hasIndex() ? 3 : 1;
|
||||
}
|
||||
return len;
|
||||
} else if (frameType == Const.FULL_FRAME) {
|
||||
int len = 7;
|
||||
for (final StackMapType types_of_local : typesOfLocals) {
|
||||
len += types_of_local.hasIndex() ? 3 : 1;
|
||||
}
|
||||
for (final StackMapType types_of_stack_item : typesOfStackItems) {
|
||||
len += types_of_stack_item.hasIndex() ? 3 : 1;
|
||||
}
|
||||
return len;
|
||||
} else {
|
||||
throw new IllegalStateException("Invalid StackMap frameType: " + frameType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setFrameType( final int f ) {
|
||||
if (f >= Const.SAME_FRAME && f <= Const.SAME_FRAME_MAX) {
|
||||
byteCodeOffset = f - Const.SAME_FRAME;
|
||||
} else if (f >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME &&
|
||||
f <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
byteCodeOffset = f - Const.SAME_LOCALS_1_STACK_ITEM_FRAME;
|
||||
} else if (f == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else if (f >= Const.CHOP_FRAME && f <= Const.CHOP_FRAME_MAX) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else if (f == Const.SAME_FRAME_EXTENDED) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else if (f >= Const.APPEND_FRAME && f <= Const.APPEND_FRAME_MAX) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else if (f == Const.FULL_FRAME) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid StackMap frameType");
|
||||
}
|
||||
frameType = f;
|
||||
}
|
||||
|
||||
|
||||
public int getFrameType() {
|
||||
return frameType;
|
||||
}
|
||||
|
||||
|
||||
public void setByteCodeOffset( final int new_offset ) {
|
||||
if (new_offset < 0 || new_offset > 32767) {
|
||||
throw new IllegalArgumentException("Invalid StackMap offset: " + new_offset);
|
||||
}
|
||||
|
||||
if (frameType >= Const.SAME_FRAME &&
|
||||
frameType <= Const.SAME_FRAME_MAX) {
|
||||
if (new_offset > Const.SAME_FRAME_MAX) {
|
||||
frameType = Const.SAME_FRAME_EXTENDED;
|
||||
} else {
|
||||
frameType = new_offset;
|
||||
}
|
||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME &&
|
||||
frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||
if (new_offset > Const.SAME_FRAME_MAX) {
|
||||
frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
|
||||
} else {
|
||||
frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME + new_offset;
|
||||
}
|
||||
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else if (frameType >= Const.CHOP_FRAME &&
|
||||
frameType <= Const.CHOP_FRAME_MAX) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else if (frameType == Const.SAME_FRAME_EXTENDED) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else if (frameType >= Const.APPEND_FRAME &&
|
||||
frameType <= Const.APPEND_FRAME_MAX) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else if (frameType == Const.FULL_FRAME) { // CHECKSTYLE IGNORE EmptyBlock
|
||||
} else {
|
||||
throw new IllegalStateException("Invalid StackMap frameType: " + frameType);
|
||||
}
|
||||
byteCodeOffset = new_offset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the distance (as an offset delta) from this StackMap
|
||||
* entry to the next. Note that this might cause the the
|
||||
* frame type to change. Note also that delta may be negative.
|
||||
* Update the distance (as an offset delta) from this StackMap entry to the next. Note that this might cause the
|
||||
* frame type to change. Note also that delta may be negative.
|
||||
*
|
||||
* @param delta offset delta
|
||||
*/
|
||||
public void updateByteCodeOffset(final int delta) {
|
||||
setByteCodeOffset(byteCodeOffset + delta);
|
||||
}
|
||||
|
||||
|
||||
public int getByteCodeOffset() {
|
||||
return byteCodeOffset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated since 6.0
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public void setNumberOfLocals( final int n ) { // TODO unused
|
||||
}
|
||||
|
||||
|
||||
public int getNumberOfLocals() {
|
||||
return typesOfLocals.length;
|
||||
}
|
||||
|
||||
|
||||
public void setTypesOfLocals( final StackMapType[] types ) {
|
||||
typesOfLocals = types != null ? types : new StackMapType[0];
|
||||
}
|
||||
|
||||
|
||||
public StackMapType[] getTypesOfLocals() {
|
||||
return typesOfLocals;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated since 6.0
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public void setNumberOfStackItems( final int n ) { // TODO unused
|
||||
}
|
||||
|
||||
|
||||
public int getNumberOfStackItems() {
|
||||
return typesOfStackItems.length;
|
||||
}
|
||||
|
||||
|
||||
public void setTypesOfStackItems( final StackMapType[] types ) {
|
||||
typesOfStackItems = types != null ? types : new StackMapType[0];
|
||||
}
|
||||
|
||||
|
||||
public StackMapType[] getTypesOfStackItems() {
|
||||
return typesOfStackItems;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
public StackMapEntry copy() {
|
||||
StackMapEntry e;
|
||||
try {
|
||||
e = (StackMapEntry) clone();
|
||||
} catch (final CloneNotSupportedException ex) {
|
||||
throw new Error("Clone Not Supported");
|
||||
}
|
||||
|
||||
e.typesOfLocals = new StackMapType[typesOfLocals.length];
|
||||
for (int i = 0; i < typesOfLocals.length; i++) {
|
||||
e.typesOfLocals[i] = typesOfLocals[i].copy();
|
||||
}
|
||||
e.typesOfStackItems = new StackMapType[typesOfStackItems.length];
|
||||
for (int i = 0; i < typesOfStackItems.length; i++) {
|
||||
e.typesOfStackItems[i] = typesOfStackItems[i].copy();
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
v.visitStackMapEntry(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Constant pool used by this object.
|
||||
*/
|
||||
public ConstantPool getConstantPool() {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
*/
|
||||
public void setConstantPool( final ConstantPool constantPool ) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,118 +28,51 @@ import java.io.IOException;
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents the type of a local variable or item on stack
|
||||
* used in the StackMap entries.
|
||||
* This class represents the type of a local variable or item on stack used in the StackMap entries.
|
||||
*
|
||||
* @see StackMapEntry
|
||||
* @see StackMap
|
||||
* @see Const
|
||||
* @see StackMapEntry
|
||||
* @see StackMap
|
||||
* @see Const
|
||||
*/
|
||||
public final class StackMapType implements Cloneable {
|
||||
|
||||
public static final StackMapType[] EMPTY_ARRAY = {}; // must be public because BCELifier code generator writes calls to it
|
||||
|
||||
private byte type;
|
||||
private int index = -1; // Index to CONSTANT_Class or offset
|
||||
private ConstantPool constantPool;
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
* @param file Input stream
|
||||
* @throws IOException
|
||||
*/
|
||||
StackMapType(final DataInput file, final ConstantPool constant_pool) throws IOException {
|
||||
this(file.readByte(), -1, constant_pool);
|
||||
if (hasIndex()) {
|
||||
this.index = file.readShort();
|
||||
}
|
||||
this.constantPool = constant_pool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param type type tag as defined in the Constants interface
|
||||
* @param index index to constant pool, or byte code offset
|
||||
*/
|
||||
public StackMapType(final byte type, final int index, final ConstantPool constant_pool) {
|
||||
if ((type < Const.ITEM_Bogus) || (type > Const.ITEM_NewObject)) {
|
||||
throw new IllegalArgumentException("Illegal type for StackMapType: " + type);
|
||||
}
|
||||
this.type = type;
|
||||
public StackMapType(final byte type, final int index, final ConstantPool constantPool) {
|
||||
this.type = checkType(type);
|
||||
this.index = index;
|
||||
this.constantPool = constant_pool;
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
|
||||
public void setType( final byte t ) {
|
||||
if ((t < Const.ITEM_Bogus) || (t > Const.ITEM_NewObject)) {
|
||||
throw new IllegalArgumentException("Illegal type for StackMapType: " + t);
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
StackMapType(final DataInput file, final ConstantPool constantPool) throws IOException {
|
||||
this(file.readByte(), -1, constantPool);
|
||||
if (hasIndex()) {
|
||||
this.index = file.readUnsignedShort();
|
||||
}
|
||||
type = t;
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
|
||||
public byte getType() {
|
||||
private byte checkType(final byte type) {
|
||||
if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) {
|
||||
throw new ClassFormatException("Illegal type for StackMapType: " + type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
public void setIndex( final int t ) {
|
||||
index = t;
|
||||
}
|
||||
|
||||
|
||||
/** @return index to constant pool if type == ITEM_Object, or offset
|
||||
* in byte code, if type == ITEM_NewObject, and -1 otherwise
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump type entries to file.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
*/
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
file.writeByte(type);
|
||||
if (hasIndex()) {
|
||||
file.writeShort(getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @return true, if type is either ITEM_Object or ITEM_NewObject
|
||||
*/
|
||||
public boolean hasIndex() {
|
||||
return type == Const.ITEM_Object || type == Const.ITEM_NewObject;
|
||||
}
|
||||
|
||||
|
||||
private String printIndex() {
|
||||
if (type == Const.ITEM_Object) {
|
||||
if (index < 0) {
|
||||
return ", class=<unknown>";
|
||||
}
|
||||
return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class);
|
||||
} else if (type == Const.ITEM_NewObject) {
|
||||
return ", offset=" + index;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(type=" + Const.getItemName(type) + printIndex() + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@@ -152,6 +85,18 @@ public final class StackMapType implements Cloneable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump type entries to file.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
file.writeByte(type);
|
||||
if (hasIndex()) {
|
||||
file.writeShort(getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Constant pool used by this object.
|
||||
@@ -160,11 +105,58 @@ public final class StackMapType implements Cloneable {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index to constant pool if type == ITEM_Object, or offset in byte code, if type == ITEM_NewObject, and -1
|
||||
* otherwise
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public byte getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if type is either ITEM_Object or ITEM_NewObject
|
||||
*/
|
||||
public boolean hasIndex() {
|
||||
return type == Const.ITEM_Object || type == Const.ITEM_NewObject;
|
||||
}
|
||||
|
||||
private String printIndex() {
|
||||
if (type == Const.ITEM_Object) {
|
||||
if (index < 0) {
|
||||
return ", class=<unknown>";
|
||||
}
|
||||
return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class);
|
||||
}
|
||||
if (type == Const.ITEM_NewObject) {
|
||||
return ", offset=" + index;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
*/
|
||||
public void setConstantPool( final ConstantPool constantPool ) {
|
||||
public void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
public void setIndex(final int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public void setType(final byte type) {
|
||||
this.type = checkType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(type=" + Const.getItemName(type) + printIndex() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,58 +26,42 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class is derived from <em>Attribute</em> and declares this class as
|
||||
* `synthetic', i.e., it needs special handling. The JVM specification
|
||||
* states "A class member that does not appear in the source code must be
|
||||
* marked using a Synthetic attribute." It may appear in the ClassFile
|
||||
* attribute table, a field_info table or a method_info table. This class
|
||||
* is intended to be instantiated from the
|
||||
* <em>Attribute.readAttribute()</em> method.
|
||||
* This class is derived from <em>Attribute</em> and declares this class as 'synthetic', i.e., it needs special
|
||||
* handling. The JVM specification states "A class member that does not appear in the source code must be marked using a
|
||||
* Synthetic attribute." It may appear in the ClassFile attribute table, a field_info table or a method_info table. This
|
||||
* class is intended to be instantiated from the <em>Attribute.readAttribute()</em> method.
|
||||
*
|
||||
* @see Attribute
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class Synthetic extends Attribute {
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use copy() for a physical copy.
|
||||
*/
|
||||
public Synthetic(final Synthetic c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8, which
|
||||
* should represent the string "Synthetic".
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8, which should represent the string "Synthetic".
|
||||
* @param length Content length in bytes - should be zero.
|
||||
* @param bytes Attribute contents
|
||||
* @param constant_pool The constant pool this attribute is associated
|
||||
* with.
|
||||
* @param constantPool The constant pool this attribute is associated with.
|
||||
*/
|
||||
public Synthetic(final int name_index, final int length, final byte[] bytes, final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_SYNTHETIC, name_index, length, constant_pool);
|
||||
public Synthetic(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_SYNTHETIC, nameIndex, Args.require0(length, "Synthetic attribute length"), constantPool);
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param name_index Index in constant pool to CONSTANT_Utf8
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
Synthetic(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, (byte[]) null, constant_pool);
|
||||
Synthetic(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (byte[]) null, constantPool);
|
||||
if (length > 0) {
|
||||
bytes = new byte[length];
|
||||
input.readFully(bytes);
|
||||
@@ -85,35 +69,54 @@ public final class Synthetic extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
*
|
||||
* @param c Source to copy.
|
||||
*/
|
||||
public Synthetic(final Synthetic c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitSynthetic(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final Synthetic c = (Synthetic) clone();
|
||||
if (bytes != null) {
|
||||
c.bytes = bytes.clone();
|
||||
}
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump source file attribute to file stream in binary format.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
if (super.getLength() > 0) {
|
||||
file.write(bytes, 0, super.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return data bytes.
|
||||
*/
|
||||
@@ -121,15 +124,13 @@ public final class Synthetic extends Attribute {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bytes
|
||||
*/
|
||||
public void setBytes( final byte[] bytes ) {
|
||||
public void setBytes(final byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@@ -141,19 +142,4 @@ public final class Synthetic extends Attribute {
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final Synthetic c = (Synthetic) clone();
|
||||
if (bytes != null) {
|
||||
c.bytes = new byte[bytes.length];
|
||||
System.arraycopy(bytes, 0, c.bytes, 0, bytes.length);
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,19 +24,15 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* This class represents a reference to an unknown (i.e.,
|
||||
* application-specific) attribute of a class. It is instantiated from the
|
||||
* {@link Attribute#readAttribute(java.io.DataInput, ConstantPool)} method.
|
||||
* Applications that need to read in application-specific attributes should create an
|
||||
* {@link UnknownAttributeReader} implementation and attach it via
|
||||
* This class represents a reference to an unknown (i.e., application-specific) attribute of a class. It is instantiated
|
||||
* from the {@link Attribute#readAttribute(java.io.DataInput, ConstantPool)} method. Applications that need to read in
|
||||
* application-specific attributes should create an {@link UnknownAttributeReader} implementation and attach it via
|
||||
* {@link Attribute#addAttributeReader(String, UnknownAttributeReader)}.
|
||||
|
||||
*
|
||||
* @see Attribute
|
||||
* @see UnknownAttributeReader
|
||||
@@ -44,93 +40,87 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
public final class Unknown extends Attribute {
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
private final String name;
|
||||
private static final Map<String, Unknown> unknownAttributes = new HashMap<>();
|
||||
|
||||
|
||||
/** @return array of unknown attributes, but just one for each kind.
|
||||
*/
|
||||
static Unknown[] getUnknownAttributes() {
|
||||
final Unknown[] unknowns = new Unknown[unknownAttributes.size()];
|
||||
unknownAttributes.values().toArray(unknowns);
|
||||
unknownAttributes.clear();
|
||||
return unknowns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize from another object. Note that both objects use the same
|
||||
* references (shallow copy). Use clone() for a physical copy.
|
||||
*/
|
||||
public Unknown(final Unknown c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a non-standard attribute.
|
||||
* Constructs a new instance for a non-standard attribute.
|
||||
*
|
||||
* @param name_index Index in constant pool
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param bytes Attribute contents
|
||||
* @param constant_pool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public Unknown(final int name_index, final int length, final byte[] bytes, final ConstantPool constant_pool) {
|
||||
super(Const.ATTR_UNKNOWN, name_index, length, constant_pool);
|
||||
public Unknown(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_UNKNOWN, nameIndex, length, constantPool);
|
||||
this.bytes = bytes;
|
||||
name = ((ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8))
|
||||
.getBytes();
|
||||
unknownAttributes.put(name, this);
|
||||
this.name = constantPool.getConstantUtf8(nameIndex).getBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* Constructs a new instance from an input stream.
|
||||
*
|
||||
* @param name_index Index in constant pool
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constant_pool Array of constants
|
||||
* @throws IOException
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
Unknown(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool)
|
||||
throws IOException {
|
||||
this(name_index, length, (byte[]) null, constant_pool);
|
||||
Unknown(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
this(nameIndex, length, (byte[]) null, constantPool);
|
||||
if (length > 0) {
|
||||
bytes = new byte[length];
|
||||
input.readFully(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance from another instance. Note that both objects use the same references (shallow copy). Use clone() for a physical copy.
|
||||
*
|
||||
* @param unknown Source.
|
||||
*/
|
||||
public Unknown(final Unknown unknown) {
|
||||
this(unknown.getNameIndex(), unknown.getLength(), unknown.getBytes(), unknown.getConstantPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by objects that are traversing the nodes of the tree implicitely
|
||||
* defined by the contents of a Java class. I.e., the hierarchy of methods,
|
||||
* fields, attributes, etc. spawns a tree of objects.
|
||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
||||
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitUnknown(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump unknown bytes to file stream.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public void dump( final DataOutputStream file ) throws IOException {
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final Unknown c = (Unknown) clone();
|
||||
if (bytes != null) {
|
||||
c.bytes = bytes.clone();
|
||||
}
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps unknown bytes to file stream.
|
||||
*
|
||||
* @param file Output file stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@Override
|
||||
public void dump(final DataOutputStream file) throws IOException {
|
||||
super.dump(file);
|
||||
if (super.getLength() > 0) {
|
||||
file.write(bytes, 0, super.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return data bytes.
|
||||
*/
|
||||
@@ -138,7 +128,6 @@ public final class Unknown extends Attribute {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return name of attribute.
|
||||
*/
|
||||
@@ -147,15 +136,13 @@ public final class Unknown extends Attribute {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bytes the bytes to set
|
||||
*/
|
||||
public void setBytes( final byte[] bytes ) {
|
||||
public void setBytes(final byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
@@ -165,28 +152,13 @@ public final class Unknown extends Attribute {
|
||||
return "(Unknown attribute " + name + ")";
|
||||
}
|
||||
String hex;
|
||||
if (super.getLength() > 10) {
|
||||
final byte[] tmp = new byte[10];
|
||||
System.arraycopy(bytes, 0, tmp, 0, 10);
|
||||
final int limit = 10;
|
||||
if (super.getLength() > limit) {
|
||||
final byte[] tmp = Arrays.copyOf(bytes, limit);
|
||||
hex = Utility.toHexString(tmp) + "... (truncated)";
|
||||
} else {
|
||||
hex = Utility.toHexString(bytes);
|
||||
}
|
||||
return "(Unknown attribute " + name + ": " + hex + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy( final ConstantPool _constant_pool ) {
|
||||
final Unknown c = (Unknown) clone();
|
||||
if (bytes != null) {
|
||||
c.bytes = new byte[bytes.length];
|
||||
System.arraycopy(bytes, 0, c.bytes, 0, bytes.length);
|
||||
}
|
||||
c.setConstantPool(_constant_pool);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
/**
|
||||
* Unknown (non-standard) attributes may be read via user-defined factory
|
||||
* objects that can be registered with the Attribute.addAttributeReader
|
||||
* method. These factory objects should implement this interface.
|
||||
* Unknown (non-standard) attributes may be read via user-defined factory objects that can be registered with the
|
||||
* Attribute.addAttributeReader method. These factory objects should implement this interface.
|
||||
*
|
||||
* @see Attribute
|
||||
* @since 6.0
|
||||
@@ -32,22 +31,20 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
public interface UnknownAttributeReader {
|
||||
|
||||
/**
|
||||
* When this attribute reader is added via the static method Attribute.addAttributeReader,
|
||||
* an attribute name is associated with it. As the class file parser parses attributes,
|
||||
* it will call various AttributeReaders based on the name of the attributes it is constructing.
|
||||
* When this attribute reader is added via the static method Attribute.addAttributeReader, an attribute name is
|
||||
* associated with it. As the class file parser parses attributes, it will call various AttributeReaders based on the
|
||||
* name of the attributes it is constructing.
|
||||
*
|
||||
* @param name_index An index into the constant pool, indexing a ConstantUtf8
|
||||
* that represents the name of the attribute.
|
||||
* @param length The length of the data contained in the attribute. This is written
|
||||
* into the constant pool and should agree with what the factory expects the length to be.
|
||||
* @param file This is the data input that the factory needs to read its data from.
|
||||
* @param constant_pool This is the constant pool associated with the Attribute that we are constructing.
|
||||
* @param nameIndex An index into the constant pool, indexing a ConstantUtf8 that represents the name of the attribute.
|
||||
* @param length The length of the data contained in the attribute. This is written into the constant pool and should
|
||||
* agree with what the factory expects the length to be.
|
||||
* @param file This is the data input that the factory needs to read its data from.
|
||||
* @param constantPool This is the constant pool associated with the Attribute that we are constructing.
|
||||
*
|
||||
* @return The user-defined AttributeReader should take this data and use
|
||||
* it to construct an attribute. In the case of errors, a null can be
|
||||
* returned which will cause the parsing of the class file to fail.
|
||||
* @return The user-defined AttributeReader should take this data and use it to construct an attribute. In the case of
|
||||
* errors, a null can be returned which will cause the parsing of the class file to fail.
|
||||
*
|
||||
* @see Attribute#addAttributeReader(String, UnknownAttributeReader)
|
||||
*/
|
||||
Attribute createAttribute( int name_index, int length, java.io.DataInput file, ConstantPool constant_pool );
|
||||
Attribute createAttribute(int nameIndex, int length, java.io.DataInput file, ConstantPool constantPool);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,13 +22,30 @@
|
||||
package com.sun.org.apache.bcel.internal.classfile;
|
||||
|
||||
/**
|
||||
* Interface to make use of the Visitor pattern programming style. I.e. a class
|
||||
* that implements this interface can traverse the contents of a Java class just
|
||||
* by calling the `accept' method which all classes have.
|
||||
*
|
||||
* Interface to make use of the Visitor pattern programming style. I.e. a class that implements this interface can
|
||||
* traverse the contents of a Java class just by calling the 'accept' method which all classes have.
|
||||
*/
|
||||
public interface Visitor
|
||||
{
|
||||
public interface Visitor {
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitAnnotation(Annotations obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitAnnotationDefault(AnnotationDefault obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitAnnotationEntry(AnnotationEntry obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitBootstrapMethods(BootstrapMethods obj);
|
||||
|
||||
void visitCode(Code obj);
|
||||
|
||||
void visitCodeException(CodeException obj);
|
||||
@@ -37,6 +54,13 @@ public interface Visitor
|
||||
|
||||
void visitConstantDouble(ConstantDouble obj);
|
||||
|
||||
/**
|
||||
* @since 6.3
|
||||
*/
|
||||
default void visitConstantDynamic(final ConstantDynamic constantDynamic) {
|
||||
// empty
|
||||
}
|
||||
|
||||
void visitConstantFieldref(ConstantFieldref obj);
|
||||
|
||||
void visitConstantFloat(ConstantFloat obj);
|
||||
@@ -49,10 +73,30 @@ public interface Visitor
|
||||
|
||||
void visitConstantLong(ConstantLong obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitConstantMethodHandle(ConstantMethodHandle obj);
|
||||
|
||||
void visitConstantMethodref(ConstantMethodref obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitConstantMethodType(ConstantMethodType obj);
|
||||
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
void visitConstantModule(ConstantModule constantModule);
|
||||
|
||||
void visitConstantNameAndType(ConstantNameAndType obj);
|
||||
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
void visitConstantPackage(ConstantPackage constantPackage);
|
||||
|
||||
void visitConstantPool(ConstantPool obj);
|
||||
|
||||
void visitConstantString(ConstantString obj);
|
||||
@@ -63,6 +107,11 @@ public interface Visitor
|
||||
|
||||
void visitDeprecated(Deprecated obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitEnclosingMethod(EnclosingMethod obj);
|
||||
|
||||
void visitExceptionTable(ExceptionTable obj);
|
||||
|
||||
void visitField(Field obj);
|
||||
@@ -81,59 +130,12 @@ public interface Visitor
|
||||
|
||||
void visitLocalVariableTable(LocalVariableTable obj);
|
||||
|
||||
void visitMethod(Method obj);
|
||||
|
||||
void visitSignature(Signature obj);
|
||||
|
||||
void visitSourceFile(SourceFile obj);
|
||||
|
||||
void visitSynthetic(Synthetic obj);
|
||||
|
||||
void visitUnknown(Unknown obj);
|
||||
|
||||
void visitStackMap(StackMap obj);
|
||||
|
||||
void visitStackMapEntry(StackMapEntry obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitAnnotation(Annotations obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitParameterAnnotation(ParameterAnnotations obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitAnnotationEntry(AnnotationEntry obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitAnnotationDefault(AnnotationDefault obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitLocalVariableTypeTable(LocalVariableTypeTable obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitEnclosingMethod(EnclosingMethod obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitBootstrapMethods(BootstrapMethods obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitMethodParameters(MethodParameters obj);
|
||||
void visitMethod(Method obj);
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
@@ -145,34 +147,7 @@ public interface Visitor
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitConstantMethodType(ConstantMethodType obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitConstantMethodHandle(ConstantMethodHandle obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitParameterAnnotationEntry(ParameterAnnotationEntry obj);
|
||||
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
void visitConstantPackage(ConstantPackage constantPackage);
|
||||
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
void visitConstantModule(ConstantModule constantModule);
|
||||
|
||||
/**
|
||||
* @since 6.3
|
||||
*/
|
||||
default void visitConstantDynamic(final ConstantDynamic constantDynamic) {
|
||||
// empty
|
||||
}
|
||||
void visitMethodParameters(MethodParameters obj);
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
@@ -181,13 +156,6 @@ public interface Visitor
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
default void visitModuleRequires(final ModuleRequires constantModule) {
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@@ -198,14 +166,14 @@ public interface Visitor
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
default void visitModuleOpens(final ModuleOpens constantModule) {
|
||||
default void visitModuleMainClass(final ModuleMainClass obj) {
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
default void visitModuleProvides(final ModuleProvides constantModule) {
|
||||
default void visitModuleOpens(final ModuleOpens constantModule) {
|
||||
// empty
|
||||
}
|
||||
|
||||
@@ -219,7 +187,14 @@ public interface Visitor
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
default void visitModuleMainClass(final ModuleMainClass obj) {
|
||||
default void visitModuleProvides(final ModuleProvides constantModule) {
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
default void visitModuleRequires(final ModuleRequires constantModule) {
|
||||
// empty
|
||||
}
|
||||
|
||||
@@ -236,4 +211,26 @@ public interface Visitor
|
||||
default void visitNestMembers(final NestMembers obj) {
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitParameterAnnotation(ParameterAnnotations obj);
|
||||
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
void visitParameterAnnotationEntry(ParameterAnnotationEntry obj);
|
||||
|
||||
void visitSignature(Signature obj);
|
||||
|
||||
void visitSourceFile(SourceFile obj);
|
||||
|
||||
void visitStackMap(StackMap obj);
|
||||
|
||||
void visitStackMapEntry(StackMapEntry obj);
|
||||
|
||||
void visitSynthetic(Synthetic obj);
|
||||
|
||||
void visitUnknown(Unknown obj);
|
||||
}
|
||||
|
||||
@@ -23,28 +23,28 @@ package com.sun.org.apache.bcel.internal.generic;
|
||||
|
||||
/**
|
||||
* AALOAD - Load reference from array
|
||||
* <PRE>Stack: ..., arrayref, index -> value</PRE>
|
||||
*
|
||||
* <PRE>
|
||||
* Stack: ..., arrayref, index -> value
|
||||
* </PRE>
|
||||
*/
|
||||
public class AALOAD extends ArrayInstruction implements StackProducer {
|
||||
|
||||
/** Load reference from array
|
||||
/**
|
||||
* Load reference from array
|
||||
*/
|
||||
public AALOAD() {
|
||||
super(com.sun.org.apache.bcel.internal.Const.AALOAD);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call corresponding visitor method(s). The order is:
|
||||
* Call visitor methods of implemented interfaces first, then
|
||||
* call methods according to the class hierarchy in descending order,
|
||||
* i.e., the most specific visitXXX() call comes last.
|
||||
* Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
|
||||
* methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitStackProducer(this);
|
||||
v.visitExceptionThrower(this);
|
||||
v.visitTypedInstruction(this);
|
||||
|
||||
@@ -22,29 +22,29 @@
|
||||
package com.sun.org.apache.bcel.internal.generic;
|
||||
|
||||
/**
|
||||
* AASTORE - Store into reference array
|
||||
* <PRE>Stack: ..., arrayref, index, value -> ...</PRE>
|
||||
* AASTORE - Store into reference array
|
||||
*
|
||||
* <PRE>
|
||||
* Stack: ..., arrayref, index, value -> ...
|
||||
* </PRE>
|
||||
*/
|
||||
public class AASTORE extends ArrayInstruction implements StackConsumer {
|
||||
|
||||
/** Store into reference array
|
||||
/**
|
||||
* Store into reference array
|
||||
*/
|
||||
public AASTORE() {
|
||||
super(com.sun.org.apache.bcel.internal.Const.AASTORE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call corresponding visitor method(s). The order is:
|
||||
* Call visitor methods of implemented interfaces first, then
|
||||
* call methods according to the class hierarchy in descending order,
|
||||
* i.e., the most specific visitXXX() call comes last.
|
||||
* Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
|
||||
* methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitStackConsumer(this);
|
||||
v.visitExceptionThrower(this);
|
||||
v.visitTypedInstruction(this);
|
||||
|
||||
@@ -23,8 +23,10 @@ package com.sun.org.apache.bcel.internal.generic;
|
||||
|
||||
/**
|
||||
* ACONST_NULL - Push null reference
|
||||
* <PRE>Stack: ... -> ..., null</PRE>
|
||||
*
|
||||
* <PRE>
|
||||
* Stack: ... -> ..., null
|
||||
* </PRE>
|
||||
*/
|
||||
public class ACONST_NULL extends Instruction implements PushInstruction, TypedInstruction {
|
||||
|
||||
@@ -35,28 +37,25 @@ public class ACONST_NULL extends Instruction implements PushInstruction, TypedIn
|
||||
super(com.sun.org.apache.bcel.internal.Const.ACONST_NULL, (short) 1);
|
||||
}
|
||||
|
||||
|
||||
/** @return Type.NULL
|
||||
*/
|
||||
@Override
|
||||
public Type getType( final ConstantPoolGen cp ) {
|
||||
return Type.NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call corresponding visitor method(s). The order is:
|
||||
* Call visitor methods of implemented interfaces first, then
|
||||
* call methods according to the class hierarchy in descending order,
|
||||
* i.e., the most specific visitXXX() call comes last.
|
||||
* Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
|
||||
* methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitStackProducer(this);
|
||||
v.visitPushInstruction(this);
|
||||
v.visitTypedInstruction(this);
|
||||
v.visitACONST_NULL(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Type.NULL
|
||||
*/
|
||||
@Override
|
||||
public Type getType(final ConstantPoolGen cp) {
|
||||
return Type.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,43 +20,40 @@
|
||||
|
||||
package com.sun.org.apache.bcel.internal.generic;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* ALOAD - Load reference from local variable
|
||||
* <PRE>Stack: ... -> ..., objectref</PRE>
|
||||
*
|
||||
* <PRE>
|
||||
* Stack: ... -> ..., objectref
|
||||
* </PRE>
|
||||
* @LastModified: Jan 2020
|
||||
*/
|
||||
public class ALOAD extends LoadInstruction {
|
||||
|
||||
/**
|
||||
* Empty constructor needed for Instruction.readInstruction.
|
||||
* Not to be used otherwise.
|
||||
* Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
|
||||
*/
|
||||
ALOAD() {
|
||||
super(Const.ALOAD, Const.ALOAD_0);
|
||||
super(com.sun.org.apache.bcel.internal.Const.ALOAD, com.sun.org.apache.bcel.internal.Const.ALOAD_0);
|
||||
}
|
||||
|
||||
|
||||
/** Load reference from local variable
|
||||
/**
|
||||
* Load reference from local variable
|
||||
*
|
||||
* @param n index of local variable
|
||||
*/
|
||||
public ALOAD(final int n) {
|
||||
super(Const.ALOAD, Const.ALOAD_0, n);
|
||||
super(com.sun.org.apache.bcel.internal.Const.ALOAD, com.sun.org.apache.bcel.internal.Const.ALOAD_0, n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call corresponding visitor method(s). The order is:
|
||||
* Call visitor methods of implemented interfaces first, then
|
||||
* call methods according to the class hierarchy in descending order,
|
||||
* i.e., the most specific visitXXX() call comes last.
|
||||
* Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
|
||||
* methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
super.accept(v);
|
||||
v.visitALOAD(this);
|
||||
}
|
||||
|
||||
@@ -24,43 +24,32 @@ package com.sun.org.apache.bcel.internal.generic;
|
||||
import com.sun.org.apache.bcel.internal.ExceptionConst;
|
||||
|
||||
/**
|
||||
* ANEWARRAY - Create new array of references
|
||||
* <PRE>Stack: ..., count -> ..., arrayref</PRE>
|
||||
* ANEWARRAY - Create new array of references
|
||||
*
|
||||
* <PRE>
|
||||
* Stack: ..., count -> ..., arrayref
|
||||
* </PRE>
|
||||
*/
|
||||
public class ANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction,
|
||||
ExceptionThrower, StackConsumer, StackProducer {
|
||||
public class ANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction, ExceptionThrower, StackConsumer, StackProducer {
|
||||
|
||||
/**
|
||||
* Empty constructor needed for Instruction.readInstruction.
|
||||
* Not to be used otherwise.
|
||||
* Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
|
||||
*/
|
||||
ANEWARRAY() {
|
||||
}
|
||||
|
||||
|
||||
public ANEWARRAY(final int index) {
|
||||
super(com.sun.org.apache.bcel.internal.Const.ANEWARRAY, index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<?>[] getExceptions() {
|
||||
return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION,
|
||||
ExceptionConst.NEGATIVE_ARRAY_SIZE_EXCEPTION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call corresponding visitor method(s). The order is:
|
||||
* Call visitor methods of implemented interfaces first, then
|
||||
* call methods according to the class hierarchy in descending order,
|
||||
* i.e., the most specific visitXXX() call comes last.
|
||||
* Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
|
||||
* methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitLoadClass(this);
|
||||
v.visitAllocationInstruction(this);
|
||||
v.visitExceptionThrower(this);
|
||||
@@ -70,13 +59,17 @@ public class ANEWARRAY extends CPInstruction implements LoadClass, AllocationIns
|
||||
v.visitANEWARRAY(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getExceptions() {
|
||||
return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, ExceptionConst.NEGATIVE_ARRAY_SIZE_EXCEPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectType getLoadClassType( final ConstantPoolGen cpg ) {
|
||||
public ObjectType getLoadClassType(final ConstantPoolGen cpg) {
|
||||
Type t = getType(cpg);
|
||||
if (t instanceof ArrayType) {
|
||||
t = ((ArrayType) t).getBasicType();
|
||||
}
|
||||
return (t instanceof ObjectType) ? (ObjectType) t : null;
|
||||
return t instanceof ObjectType ? (ObjectType) t : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
package com.sun.org.apache.bcel.internal.generic;
|
||||
|
||||
/**
|
||||
* ARETURN - Return reference from method
|
||||
* <PRE>Stack: ..., objectref -> <empty></PRE>
|
||||
* ARETURN - Return reference from method
|
||||
*
|
||||
* <PRE>
|
||||
* Stack: ..., objectref -> <empty>
|
||||
* </PRE>
|
||||
*/
|
||||
public class ARETURN extends ReturnInstruction {
|
||||
|
||||
@@ -35,17 +37,14 @@ public class ARETURN extends ReturnInstruction {
|
||||
super(com.sun.org.apache.bcel.internal.Const.ARETURN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call corresponding visitor method(s). The order is:
|
||||
* Call visitor methods of implemented interfaces first, then
|
||||
* call methods according to the class hierarchy in descending order,
|
||||
* i.e., the most specific visitXXX() call comes last.
|
||||
* Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
|
||||
* methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitExceptionThrower(this);
|
||||
v.visitTypedInstruction(this);
|
||||
v.visitStackConsumer(this);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@@ -23,43 +23,40 @@ package com.sun.org.apache.bcel.internal.generic;
|
||||
import com.sun.org.apache.bcel.internal.ExceptionConst;
|
||||
|
||||
/**
|
||||
* ARRAYLENGTH - Get length of array
|
||||
* <PRE>Stack: ..., arrayref -> ..., length</PRE>
|
||||
* ARRAYLENGTH - Get length of array
|
||||
*
|
||||
* @LastModified: Jun 2019
|
||||
* <PRE>
|
||||
* Stack: ..., arrayref -> ..., length
|
||||
* </PRE>
|
||||
* @LastModified: Feb 2023
|
||||
*/
|
||||
public class ARRAYLENGTH extends Instruction
|
||||
implements ExceptionThrower, StackProducer, StackConsumer /* since 6.0 */ {
|
||||
public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackProducer, StackConsumer /* since 6.0 */ {
|
||||
|
||||
/** Get length of array
|
||||
/**
|
||||
* Get length of array
|
||||
*/
|
||||
public ARRAYLENGTH() {
|
||||
super(com.sun.org.apache.bcel.internal.Const.ARRAYLENGTH, (short) 1);
|
||||
}
|
||||
|
||||
|
||||
/** @return exceptions this instruction may cause
|
||||
*/
|
||||
@Override
|
||||
public Class<?>[] getExceptions() {
|
||||
return new Class<?>[] {
|
||||
ExceptionConst.NULL_POINTER_EXCEPTION
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call corresponding visitor method(s). The order is:
|
||||
* Call visitor methods of implemented interfaces first, then
|
||||
* call methods according to the class hierarchy in descending order,
|
||||
* i.e., the most specific visitXXX() call comes last.
|
||||
* Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
|
||||
* methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitExceptionThrower(this);
|
||||
v.visitStackProducer(this);
|
||||
v.visitARRAYLENGTH(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return exceptions this instruction may cause
|
||||
*/
|
||||
@Override
|
||||
public Class<?>[] getExceptions() {
|
||||
return new Class<?>[] {ExceptionConst.NULL_POINTER_EXCEPTION};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,43 +19,40 @@
|
||||
*/
|
||||
package com.sun.org.apache.bcel.internal.generic;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* ASTORE - Store reference into local variable
|
||||
* <PRE>Stack ..., objectref -> ... </PRE>
|
||||
*
|
||||
* <PRE>
|
||||
* Stack ..., objectref -> ...
|
||||
* </PRE>
|
||||
* @LastModified: Jan 2020
|
||||
*/
|
||||
public class ASTORE extends StoreInstruction {
|
||||
|
||||
/**
|
||||
* Empty constructor needed for Instruction.readInstruction.
|
||||
* Not to be used otherwise.
|
||||
* Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
|
||||
*/
|
||||
ASTORE() {
|
||||
super(Const.ASTORE, Const.ASTORE_0);
|
||||
super(com.sun.org.apache.bcel.internal.Const.ASTORE, com.sun.org.apache.bcel.internal.Const.ASTORE_0);
|
||||
}
|
||||
|
||||
|
||||
/** Store reference into local variable
|
||||
/**
|
||||
* Store reference into local variable
|
||||
*
|
||||
* @param n index of local variable
|
||||
*/
|
||||
public ASTORE(final int n) {
|
||||
super(Const.ASTORE, Const.ASTORE_0, n);
|
||||
super(com.sun.org.apache.bcel.internal.Const.ASTORE, com.sun.org.apache.bcel.internal.Const.ASTORE_0, n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call corresponding visitor method(s). The order is:
|
||||
* Call visitor methods of implemented interfaces first, then
|
||||
* call methods according to the class hierarchy in descending order,
|
||||
* i.e., the most specific visitXXX() call comes last.
|
||||
* Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
|
||||
* methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
super.accept(v);
|
||||
v.visitASTORE(this);
|
||||
}
|
||||
|
||||
@@ -23,43 +23,39 @@ package com.sun.org.apache.bcel.internal.generic;
|
||||
import com.sun.org.apache.bcel.internal.ExceptionConst;
|
||||
|
||||
/**
|
||||
* ATHROW - Throw exception
|
||||
* <PRE>Stack: ..., objectref -> objectref</PRE>
|
||||
* ATHROW - Throw exception
|
||||
*
|
||||
* @LastModified: Jan 2020
|
||||
* <PRE>
|
||||
* Stack: ..., objectref -> objectref
|
||||
* </PRE>
|
||||
*/
|
||||
public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower {
|
||||
|
||||
/**
|
||||
* Throw exception
|
||||
* Throw exception
|
||||
*/
|
||||
public ATHROW() {
|
||||
super(com.sun.org.apache.bcel.internal.Const.ATHROW, (short) 1);
|
||||
}
|
||||
|
||||
|
||||
/** @return exceptions this instruction may cause
|
||||
*/
|
||||
@Override
|
||||
public Class<?>[] getExceptions() {
|
||||
return new Class<?>[] {
|
||||
ExceptionConst.THROWABLE
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call corresponding visitor method(s). The order is:
|
||||
* Call visitor methods of implemented interfaces first, then
|
||||
* call methods according to the class hierarchy in descending order,
|
||||
* i.e., the most specific visitXXX() call comes last.
|
||||
* Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
|
||||
* methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
|
||||
*
|
||||
* @param v Visitor object
|
||||
*/
|
||||
@Override
|
||||
public void accept( final Visitor v ) {
|
||||
public void accept(final Visitor v) {
|
||||
v.visitUnconditionalBranch(this);
|
||||
v.visitExceptionThrower(this);
|
||||
v.visitATHROW(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return exceptions this instruction may cause
|
||||
*/
|
||||
@Override
|
||||
public Class<?>[] getExceptions() {
|
||||
return new Class<?>[] {ExceptionConst.THROWABLE};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ package com.sun.org.apache.bcel.internal.generic;
|
||||
|
||||
/**
|
||||
* Denote family of instructions that allocates space in the heap.
|
||||
*
|
||||
*/
|
||||
public interface AllocationInstruction {
|
||||
}
|
||||
|
||||
@@ -30,61 +30,48 @@ import com.sun.org.apache.bcel.internal.classfile.ElementValue;
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
public class AnnotationElementValueGen extends ElementValueGen
|
||||
{
|
||||
public class AnnotationElementValueGen extends ElementValueGen {
|
||||
// For annotation element values, this is the annotation
|
||||
private final AnnotationEntryGen a;
|
||||
|
||||
public AnnotationElementValueGen(final AnnotationEntryGen a, final ConstantPoolGen cpool)
|
||||
{
|
||||
super(ANNOTATION, cpool);
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public AnnotationElementValueGen(final int type, final AnnotationEntryGen annotation,
|
||||
final ConstantPoolGen cpool)
|
||||
{
|
||||
super(type, cpool);
|
||||
if (type != ANNOTATION) {
|
||||
throw new IllegalArgumentException(
|
||||
"Only element values of type annotation can be built with this ctor - type specified: " + type);
|
||||
}
|
||||
this.a = annotation;
|
||||
}
|
||||
|
||||
public AnnotationElementValueGen(final AnnotationElementValue value,
|
||||
final ConstantPoolGen cpool, final boolean copyPoolEntries)
|
||||
{
|
||||
public AnnotationElementValueGen(final AnnotationElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
|
||||
super(ANNOTATION, cpool);
|
||||
a = new AnnotationEntryGen(value.getAnnotationEntry(), cpool, copyPoolEntries);
|
||||
}
|
||||
|
||||
public AnnotationElementValueGen(final AnnotationEntryGen a, final ConstantPoolGen cpool) {
|
||||
super(ANNOTATION, cpool);
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public AnnotationElementValueGen(final int type, final AnnotationEntryGen annotation, final ConstantPoolGen cpool) {
|
||||
super(type, cpool);
|
||||
if (type != ANNOTATION) {
|
||||
throw new IllegalArgumentException("Only element values of type annotation can be built with this ctor - type specified: " + type);
|
||||
}
|
||||
this.a = annotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(final DataOutputStream dos) throws IOException
|
||||
{
|
||||
public void dump(final DataOutputStream dos) throws IOException {
|
||||
dos.writeByte(super.getElementValueType()); // u1 type of value (ANNOTATION == '@')
|
||||
a.dump(dos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stringifyValue()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
public AnnotationEntryGen getAnnotation() {
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return immutable variant of this AnnotationElementValueGen
|
||||
*/
|
||||
@Override
|
||||
public ElementValue getElementValue()
|
||||
{
|
||||
return new AnnotationElementValue(super.getElementValueType(),
|
||||
a.getAnnotation(),
|
||||
getConstantPool().getConstantPool());
|
||||
public ElementValue getElementValue() {
|
||||
return new AnnotationElementValue(super.getElementValueType(), a.getAnnotation(), getConstantPool().getConstantPool());
|
||||
}
|
||||
|
||||
public AnnotationEntryGen getAnnotation()
|
||||
{
|
||||
return a;
|
||||
@Override
|
||||
public String stringifyValue() {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user