
net.bytebuddy.utility.AsmClassReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of byte-buddy-dep Show documentation
Show all versions of byte-buddy-dep Show documentation
Byte Buddy is a Java library for creating Java classes at run time.
This artifact is a build of Byte Buddy with a remaining dependency onto ASM.
You should never depend on this module without repackaging Byte Buddy and ASM into your own namespace.
/*
* Copyright 2014 - Present Rafael Winterhalter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.bytebuddy.utility;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.build.AccessControllerPlugin;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.utility.dispatcher.JavaDispatcher;
import net.bytebuddy.utility.nullability.MaybeNull;
import net.bytebuddy.utility.privilege.GetSystemPropertyAction;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import java.security.PrivilegedAction;
/**
* A facade for creating a class reader that accepts {@link ClassVisitor} instances and reader flags.
*/
public interface AsmClassReader {
/**
* Indicates that no custom attributes should be mapped.
*/
Attribute[] NO_ATTRIBUTES = new Attribute[0];
/**
* Unwraps a class reader to the underlying reader mechanism.
*
* @param type The type of the reader that should be unwrapped.
* @param The type to unwrap.
* @return The unwrapped instance or {@code null} if the underlying instance does not represent this type.
*/
@MaybeNull
T unwrap(Class type);
/**
* Accepts a class visitor to read a class.
*
* @param classVisitor The class visitor who should be used as a callback for a class file.
* @param flags The flags to consider while reading a class.
*/
void accept(ClassVisitor classVisitor, int flags);
/**
* A factory to create a {@link AsmClassReader}.
*/
interface Factory {
/**
* Creates a class reader for a given class file.
*
* @param binaryRepresentation The class file's binary representation.
* @return A class reader representation for the supplied class file.
*/
AsmClassReader make(byte[] binaryRepresentation);
/**
* Creates a class reader for a given class file.
*
* @param binaryRepresentation The class file's binary representation.
* @param experimental {@code true} if unknown Java class files versions should also be considered.
* @return A class reader representation for the supplied class file.
*/
AsmClassReader make(byte[] binaryRepresentation, boolean experimental);
/**
* Default implementations for factories of {@link AsmClassReader}s.
*/
enum Default implements Factory {
/**
* Uses a processor as it is configured by {@link OpenedClassReader#PROCESSOR_PROPERTY},
* or {@link AsmClassWriter.Factory.Default#ASM_FIRST} if no implicit processor is defined.
*/
IMPLICIT {
/**
* {@inheritDoc}
*/
public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
return (FACTORY == IMPLICIT ? ASM_FIRST : FACTORY).make(binaryRepresentation, experimental);
}
},
/**
* A factory for a class reader that uses ASM's internal implementation whenever possible.
*/
ASM_FIRST {
/**
* {@inheritDoc}
*/
public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
return ClassFileVersion.ofThisVm().isGreaterThan(ClassFileVersion.latest())
? CLASS_FILE_API_ONLY.make(binaryRepresentation, experimental)
: ASM_ONLY.make(binaryRepresentation, experimental);
}
},
/**
* A factory for a class reader that uses the class file API whenever possible.
*/
CLASS_FILE_API_FIRST {
/**
* {@inheritDoc}
*/
public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
return ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V24)
? CLASS_FILE_API_ONLY.make(binaryRepresentation, experimental)
: ASM_ONLY.make(binaryRepresentation, experimental);
}
},
/**
* A factory for a class reader that always uses ASM's internal implementation.
*/
ASM_ONLY {
/**
* {@inheritDoc}
*/
public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
return new ForAsm(OpenedClassReader.of(binaryRepresentation, experimental));
}
},
/**
* A factory for a class reader that always uses the class file API.
*/
CLASS_FILE_API_ONLY {
/**
* {@inheritDoc}
*/
public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
return new AsmClassReader.ForClassFileApi(ForClassFileApi.DISPATCHER.make(
binaryRepresentation,
NO_ATTRIBUTES));
}
};
/**
* The implicit factory to use for writing class files.
*/
private static final Factory FACTORY;
/*
* Resolves the implicit reader factory, if any.
*/
static {
String processor;
try {
processor = doPrivileged(new GetSystemPropertyAction(OpenedClassReader.PROCESSOR_PROPERTY));
} catch (Throwable ignored) {
processor = null;
}
FACTORY = processor == null ? Default.ASM_FIRST : Default.valueOf(processor);
}
/**
* A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
*
* @param action The action to execute from a privileged context.
* @param The type of the action's resolved value.
* @return The action's resolved value.
*/
@MaybeNull
@AccessControllerPlugin.Enhance
private static T doPrivileged(PrivilegedAction action) {
return action.run();
}
/**
* {@inheritDoc}
*/
public AsmClassReader make(byte[] binaryRepresentation) {
return make(binaryRepresentation, OpenedClassReader.EXPERIMENTAL);
}
}
}
/**
* A class reader for ASM's own {@link ClassReader}.
*/
class ForAsm implements AsmClassReader {
/**
* The class reader that represents the class file to be read.
*/
private final ClassReader classReader;
/**
* Creates a new ASM class reader that uses ASM's internal implementation.
*
* @param classReader The class reader that represents the class file to be read.
*/
public ForAsm(ClassReader classReader) {
this.classReader = classReader;
}
/**
* {@inheritDoc}
*/
@MaybeNull
public T unwrap(Class type) {
return type.isInstance(classReader)
? type.cast(classReader)
: null;
}
/**
* {@inheritDoc}
*/
public void accept(ClassVisitor classVisitor, int flags) {
classReader.accept(classVisitor, NO_ATTRIBUTES, flags);
}
}
/**
* A class reader that is based upon the Class File API.
*/
@HashCodeAndEqualsPlugin.Enhance
class ForClassFileApi implements AsmClassReader {
/**
* A dispatcher to interact with {@code codes.rafael.asmjdkbridge.JdkClassReader}.
*/
protected static final JdkClassReader DISPATCHER = doPrivileged(JavaDispatcher.of(
JdkClassReader.class,
ForClassFileApi.class.getClassLoader()));
/**
* The class reader that represents the class file to be read.
*/
private final Object classReader;
/**
* Creates a new class reader that is based upon the Class File API.
*
* @param classReader The class reader that represents the class file to be read.
*/
public ForClassFileApi(Object classReader) {
if (!DISPATCHER.isInstance(classReader)) {
throw new IllegalArgumentException();
}
this.classReader = classReader;
}
/**
* A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
*
* @param action The action to execute from a privileged context.
* @param The type of the action's resolved value.
* @return The action's resolved value.
*/
@AccessControllerPlugin.Enhance
private static T doPrivileged(PrivilegedAction action) {
return action.run();
}
/**
* {@inheritDoc}
*/
@MaybeNull
public T unwrap(Class type) {
return type.isInstance(classReader)
? type.cast(classReader)
: null;
}
/**
* {@inheritDoc}
*/
public void accept(ClassVisitor classVisitor, int flags) {
DISPATCHER.accept(classReader, classVisitor, flags);
}
/**
* A dispatcher to interact with {@code codes.rafael.asmjdkbridge.JdkClassReader}.
*/
@JavaDispatcher.Proxied("codes.rafael.asmjdkbridge.JdkClassReader")
protected interface JdkClassReader {
/**
* Checks if the supplied object is an instance of {@code codes.rafael.asmjdkbridge.JdkClassReader}.
*
* @param value The instance to evaluate.
* @return {@code true} if the supplied object is an instance of {@code codes.rafael.asmjdkbridge.JdkClassReader}.
*/
@JavaDispatcher.Instance
boolean isInstance(Object value);
/**
* Creates an instance of {@code codes.rafael.asmjdkbridge.JdkClassReader}.
*
* @param binaryRepresentation The binary representation of a class file to represent through the reader.
* @param attribute An array of attribute prototypes.
* @return A new instance of {@code codes.rafael.asmjdkbridge.JdkClassReader}.
*/
@JavaDispatcher.IsConstructor
Object make(byte[] binaryRepresentation, Attribute[] attribute);
/**
* Accepts a class reader to visit the represented class file.
*
* @param classReader The class reader that is being visited.
* @param classVisitor The class visitor to visit the class.
* @param flags The flags to consider during reading.
*/
void accept(Object classReader, ClassVisitor classVisitor, int flags);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy