// Generated by delombok at Sun Feb 26 12:31:38 KST 2017
package scouter.bytebuddy.dynamic;
import scouter.bytebuddy.description.NamedElement;
import scouter.bytebuddy.description.type.TypeDescription;
import scouter.bytebuddy.utility.JavaModule;
import scouter.bytebuddy.utility.JavaType;
import scouter.bytebuddy.utility.StreamDrainer;
import scouter.bytebuddy.matcher.ElementMatchers;
import java.io.*;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.*;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* Locates a class file or its byte array representation when it is given its type description.
*/
public interface ClassFileLocator extends Closeable {
/**
* The file extension for a Java class file.
*/
String CLASS_FILE_EXTENSION = ".class";
/**
* Locates the class file for a given type and returns the binary data of the class file.
*
* @param typeName The name of the type to locate a class file representation for.
* @return Any binary representation of the type which might be illegal.
* @throws java.io.IOException If reading a class file causes an error.
*/
Resolution locate(String typeName) throws IOException;
/**
* Represents a class file as binary data.
*/
interface Resolution {
/**
* Checks if this binary representation is valid.
*
* @return {@code true} if this binary representation is valid.
*/
boolean isResolved();
/**
* Finds the data of this binary representation. Calling this method is only legal for resolved instances.
* For non-resolved instances, an exception is thrown.
*
* @return The requested binary data. The returned array must not be altered.
*/
byte[] resolve();
/**
* A canonical representation of an illegal binary representation.
*/
class Illegal implements Resolution {
/**
* The name of the unresolved class file.
*/
private final String typeName;
/**
* Creates an illegal resolution for a class file.
*
* @param typeName The name of the unresolved class file.
*/
public Illegal(String typeName) {
this.typeName = typeName;
}
@Override
public boolean isResolved() {
return false;
}
@Override
public byte[] resolve() {
throw new IllegalStateException("Could not locate class file for " + typeName);
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.Resolution.Illegal)) return false;
final ClassFileLocator.Resolution.Illegal other = (ClassFileLocator.Resolution.Illegal) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$typeName = this.typeName;
final java.lang.Object other$typeName = other.typeName;
if (this$typeName == null ? other$typeName != null : !this$typeName.equals(other$typeName)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.Resolution.Illegal;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $typeName = this.typeName;
result = result * PRIME + ($typeName == null ? 43 : $typeName.hashCode());
return result;
}
}
/**
* Represents a byte array as binary data.
*/
class Explicit implements Resolution {
/**
* The represented data.
*/
private final byte[] binaryRepresentation;
/**
* Creates a new explicit resolution of a given array of binary data.
*
* @param binaryRepresentation The binary data to represent. The array must not be modified.
*/
public Explicit(byte[] binaryRepresentation) {
this.binaryRepresentation = binaryRepresentation;
}
@Override
public boolean isResolved() {
return true;
}
@Override
public byte[] resolve() {
return binaryRepresentation;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.Resolution.Explicit)) return false;
final ClassFileLocator.Resolution.Explicit other = (ClassFileLocator.Resolution.Explicit) o;
if (!other.canEqual((java.lang.Object) this)) return false;
if (!java.util.Arrays.equals(this.binaryRepresentation, other.binaryRepresentation)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.Resolution.Explicit;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + java.util.Arrays.hashCode(this.binaryRepresentation);
return result;
}
}
}
/**
* A class file locator that cannot locate any class files.
*/
enum NoOp implements ClassFileLocator {
/**
* The singleton instance.
*/
INSTANCE;
@Override
public Resolution locate(String typeName) {
return new Resolution.Illegal(typeName);
}
@Override
public void close() throws IOException {
/* do nothing */
}
}
/**
* A simple class file locator that returns class files from a selection of given types.
*/
class Simple implements ClassFileLocator {
/**
* The class files that are known to this class file locator mapped by their type name.
*/
private final Map<String, byte[]> classFiles;
/**
* Creates a new simple class file locator.
*
* @param classFiles The class files that are known to this class file locator mapped by their type name.
*/
public Simple(Map<String, byte[]> classFiles) {
this.classFiles = classFiles;
}
/**
* Creates a class file locator for a single known type.
*
* @param typeName The name of the type.
* @param binaryRepresentation The binary representation of the type.
* @return An appropriate class file locator.
*/
public static ClassFileLocator of(String typeName, byte[] binaryRepresentation) {
return new Simple(Collections.singletonMap(typeName, binaryRepresentation));
}
/**
* Creates a class file locator for a single known type with an additional fallback locator.
*
* @param typeName The name of the type.
* @param binaryRepresentation The binary representation of the type.
* @param fallback The class file locator to query in case that a lookup triggers any other type.
* @return An appropriate class file locator.
*/
public static ClassFileLocator of(String typeName, byte[] binaryRepresentation, ClassFileLocator fallback) {
return new Compound(new Simple(Collections.singletonMap(typeName, binaryRepresentation)), fallback);
}
@Override
public Resolution locate(String typeName) {
byte[] binaryRepresentation = classFiles.get(typeName);
return binaryRepresentation == null ? new Resolution.Illegal(typeName) : new Resolution.Explicit(binaryRepresentation);
}
@Override
public void close() {
/* do nothing */
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.Simple)) return false;
final ClassFileLocator.Simple other = (ClassFileLocator.Simple) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$classFiles = this.classFiles;
final java.lang.Object other$classFiles = other.classFiles;
if (this$classFiles == null ? other$classFiles != null : !this$classFiles.equals(other$classFiles)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.Simple;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $classFiles = this.classFiles;
result = result * PRIME + ($classFiles == null ? 43 : $classFiles.hashCode());
return result;
}
}
/**
* <p>
* A class file locator that queries a class loader for binary representations of class files.
* </p>
* <p>
* <b>Important</b>: Even when calling {@link Closeable#close()} on this class file locator, no underlying
* class loader is closed if it implements the {@link Closeable} interface as this is typically not intended.
* </p>
*/
class ForClassLoader implements ClassFileLocator {
/**
* The class loader to query.
*/
private final ClassLoader classLoader;
/**
* Creates a new class file locator for the given class loader.
*
* @param classLoader The class loader to query which must not be the bootstrap class loader, i.e. {@code null}.
*/
protected ForClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Creates a class file locator that queries the system class loader.
*
* @return A class file locator that queries the system class loader.
*/
public static ClassFileLocator ofClassPath() {
return new ForClassLoader(ClassLoader.getSystemClassLoader());
}
/**
* Creates a class file locator for a given class loader.
*
* @param classLoader The class loader to be used. If this class loader represents the bootstrap class
* loader which is represented by the {@code null} value, this system class loader
* is used instead.
* @return A corresponding source locator.
*/
public static ClassFileLocator of(ClassLoader classLoader) {
return new ForClassLoader(classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader);
}
/**
* Attempts to create a binary representation of a loaded type by requesting data from its
* {@link java.lang.ClassLoader}.
*
* @param type The type of interest.
* @return The binary data to this type which might be illegal.
*/
public static Resolution read(Class<?> type) {
try {
ClassLoader classLoader = type.getClassLoader();
return locate(classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader, TypeDescription.ForLoadedType.getName(type));
} catch (IOException exception) {
throw new IllegalStateException("Cannot read class file for " + type, exception);
}
}
@Override
public Resolution locate(String typeName) throws IOException {
return locate(classLoader, typeName);
}
@Override
public void close() throws IOException {
/* do nothing */
}
/**
* Locates the class file for the supplied type by requesting a resource from the class loader.
*
* @param classLoader The class loader to query for the resource.
* @param typeName The name of the type for which to locate a class file.
* @return A resolution for the class file.
* @throws IOException If reading the class file causes an exception.
*/
protected static Resolution locate(ClassLoader classLoader, String typeName) throws IOException {
InputStream inputStream = classLoader.getResourceAsStream(typeName.replace('.', '/') + CLASS_FILE_EXTENSION);
if (inputStream != null) {
try {
return new Resolution.Explicit(StreamDrainer.DEFAULT.drain(inputStream));
} finally {
inputStream.close();
}
} else {
return new Resolution.Illegal(typeName);
}
}
/**
* <p>
* A class file locator that queries a class loader for binary representations of class files.
* The class loader is only weakly referenced.
* </p>
* <p>
* <b>Important</b>: Even when calling {@link Closeable#close()} on this class file locator, no underlying
* class loader is closed if it implements the {@link Closeable} interface as this is typically not intended.
* </p>
*/
public static class WeaklyReferenced extends WeakReference<ClassLoader> implements ClassFileLocator {
/**
* The represented class loader's hash code.
*/
private final int hashCode;
/**
* Creates a class file locator for a class loader that is weakly referenced.
*
* @param classLoader The class loader to represent.
*/
protected WeaklyReferenced(ClassLoader classLoader) {
super(classLoader);
hashCode = System.identityHashCode(classLoader);
}
public static ClassFileLocator of(ClassLoader classLoader) {
return classLoader == null || classLoader == ClassLoader.getSystemClassLoader() || classLoader == ClassLoader.getSystemClassLoader().getParent() ? ForClassLoader.of(classLoader) : new WeaklyReferenced(classLoader);
}
@Override
public Resolution locate(String typeName) throws IOException {
ClassLoader classLoader = get();
return classLoader == null ? new Resolution.Illegal(typeName) : ForClassLoader.locate(classLoader, typeName);
}
@Override
public void close() throws IOException {
/* do nothing */
/**
* Creates a class file locator for a given class loader. If the class loader is not the bootstrap
* class loader or the system class loader which cannot be collected, the class loader is only weakly
* referenced.
*
* @param classLoader The class loader to be used. If this class loader represents the bootstrap class
* loader which is represented by the {@code null} value, this system class loader
* is used instead.
* @return A corresponding source locator.
*/
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
WeaklyReferenced that = (WeaklyReferenced) object;
ClassLoader classLoader = that.get();
return classLoader != null && get() == classLoader;
}
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.ForClassLoader)) return false;
final ClassFileLocator.ForClassLoader other = (ClassFileLocator.ForClassLoader) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$classLoader = this.classLoader;
final java.lang.Object other$classLoader = other.classLoader;
if (this$classLoader == null ? other$classLoader != null : !this$classLoader.equals(other$classLoader)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.ForClassLoader;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $classLoader = this.classLoader;
result = result * PRIME + ($classLoader == null ? 43 : $classLoader.hashCode());
return result;
}
}
/**
* <p>
* A class file locator that locates class files by querying a Java module's {@code getResourceAsStream} method.
* </p>
* <p>
* <b>Important</b>: Even when calling {@link Closeable#close()} on this class file locator, no underlying
* class loader is closed if it implements the {@link Closeable} interface as this is typically not intended.
* </p>
*/
class ForModule implements ClassFileLocator {
/**
* The represented Java module.
*/
private final JavaModule module;
/**
* Creates a new class file locator for a Java module.
*
* @param module The represented Java module.
*/
protected ForModule(JavaModule module) {
this.module = module;
}
/**
* Returns a class file locator that exposes all class files of the boot module layer. This class file locator is only available
* on virtual machines of version 9 or later. On earlier versions, the returned class file locator does not locate any resources.
*
* @return A class file locator that locates classes of the boot layer.
*/
public static ClassFileLocator ofBootLayer() {
try {
Map<String, ClassFileLocator> bootModules = new HashMap<String, ClassFileLocator>();
Class<?> layerType = Class.forName("java.lang.reflect.Layer");
Method getPackages = JavaType.MODULE.load().getMethod("getPackages");
for (Object rawModule : (Set<?>) layerType.getMethod("modules").invoke(layerType.getMethod("boot").invoke(null))) {
ClassFileLocator classFileLocator = ForModule.of(JavaModule.of(rawModule));
for (String packageName : (String[]) getPackages.invoke(rawModule)) {
bootModules.put(packageName, classFileLocator);
}
}
return new PackageDiscriminating(bootModules);
} catch (Exception exception) {
throw new IllegalStateException("Cannot process boot layer", exception);
}
}
/**
* Returns a class file locator for the provided module. If the provided module is not named, class files are located via this
* unnamed module's class loader.
*
* @param module The module to create a class file locator for.
* @return An appropriate class file locator.
*/
public static ClassFileLocator of(JavaModule module) {
return module.isNamed() ? new ForModule(module) : ForClassLoader.of(module.getClassLoader());
}
@Override
public Resolution locate(String typeName) throws IOException {
return locate(module, typeName);
}
/**
* Creates a resolution for a Java module's class files.
*
* @param module The Java module to query.
* @param typeName The name of the type being queried.
* @return A resolution for the query.
* @throws IOException If an I/O exception was thrown.
*/
protected static Resolution locate(JavaModule module, String typeName) throws IOException {
InputStream inputStream = module.getResourceAsStream(typeName.replace('.', '/') + CLASS_FILE_EXTENSION);
if (inputStream != null) {
try {
return new Resolution.Explicit(StreamDrainer.DEFAULT.drain(inputStream));
} finally {
inputStream.close();
}
} else {
return new Resolution.Illegal(typeName);
}
}
@Override
public void close() throws IOException {
/* do nothing */
}
/**
* <p>
* A class file locator for a Java module that only references this module weakly. If a module was garbage collected,
* this class file locator only returns unresolved resolutions.
* </p>
* <p>
* <b>Important</b>: Even when calling {@link Closeable#close()} on this class file locator, no underlying
* class loader is closed if it implements the {@link Closeable} interface as this is typically not intended.
* </p>
*/
public static class WeaklyReferenced extends WeakReference<Object> implements ClassFileLocator {
/**
* The represented module's hash code.
*/
private final int hashCode;
/**
* Creates a class file locator for a Java module that is weakly referenced.
*
* @param module The raw Java module to represent.
*/
protected WeaklyReferenced(Object module) {
super(module);
hashCode = System.identityHashCode(module);
}
public static ClassFileLocator of(JavaModule module) {
if (module.isNamed()) {
return module.getClassLoader() == null || module.getClassLoader() == ClassLoader.getSystemClassLoader() || module.getClassLoader() == ClassLoader.getSystemClassLoader().getParent() ? new ForModule(module) : new WeaklyReferenced(module.unwrap());
} else {
return ForClassLoader.WeaklyReferenced.of(module.getClassLoader());
}
}
@Override
public Resolution locate(String typeName) throws IOException {
Object module = get();
return module == null ? new Resolution.Illegal(typeName) : ForModule.locate(JavaModule.of(module), typeName);
}
@Override
public void close() throws IOException {
/* do nothing */
/**
* Creates a class file locator for a Java module where the module is referenced weakly. If the module is not named, the module's class loader
* is represented instead. Module's of the boot layer are not referenced weakly.
*
* @param module The Java module to represent.
* @return A suitable class file locator.
*/
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
WeaklyReferenced that = (WeaklyReferenced) object;
Object module = that.get();
return module != null && get() == module;
}
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.ForModule)) return false;
final ClassFileLocator.ForModule other = (ClassFileLocator.ForModule) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$module = this.module;
final java.lang.Object other$module = other.module;
if (this$module == null ? other$module != null : !this$module.equals(other$module)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.ForModule;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $module = this.module;
result = result * PRIME + ($module == null ? 43 : $module.hashCode());
return result;
}
}
/**
* A class file locator that locates classes within a Java <i>jar</i> file.
*/
class ForJarFile implements ClassFileLocator {
/**
* A list of potential locations of the runtime jar for different platforms.
*/
private static final List<String> RUNTIME_LOCATIONS = Arrays.asList("lib/rt.jar", "../lib/rt.jar", "../Classes/classes.jar");
/**
* The jar file to read from.
*/
private final JarFile jarFile;
/**
* Creates a new class file locator for the given jar file.
*
* @param jarFile The jar file to read from.
*/
public ForJarFile(JarFile jarFile) {
this.jarFile = jarFile;
}
/**
* Creates a new class file locator for the given jar file.
*
* @param file The jar file to read from.
* @return A class file locator for the jar file.
* @throws IOException If an I/O exception is thrown.
*/
public static ClassFileLocator of(File file) throws IOException {
return new ForJarFile(new JarFile(file));
}
/**
* Resolves a class file locator for the class path that reads class files directly from the file system. The resulting
* class file locator does not imply classes on the boot path.
*
* @return A class file locator for the class path.
* @throws IOException If an I/O exception occurs.
*/
public static ClassFileLocator ofClassPath() throws IOException {
return ofClassPath(System.getProperty("java.class.path"));
}
/**
* <p>
* Resolves a class file locator for the class path that reads class files directly from the file system.
* </p>
* <p>
* <b>Note</b>: The resulting class file locator does not include classes of the bootstrap class loader.
* </p>
*
* @param classPath The class path to scan with the elements separated by {@code path.separator}.
* @return A class file locator for the class path.
* @throws IOException If an I/O exception occurs.
*/
public static ClassFileLocator ofClassPath(String classPath) throws IOException {
List<ClassFileLocator> classFileLocators = new ArrayList<ClassFileLocator>();
for (String element : Pattern.compile(System.getProperty("path.separator"), Pattern.LITERAL).split(classPath)) {
File file = new File(element);
if (file.isDirectory()) {
classFileLocators.add(new ForFolder(file));
} else if (file.isFile()) {
classFileLocators.add(of(file));
}
}
return new Compound(classFileLocators);
}
/**
* Resolves a class file locator for the runtime jar. If such a file does not exist or cannot be located, a runtime exception is thrown.
*
* @return A class file locator for the runtime jar, if available.
* @throws IOException If an I/O exception occurs.
*/
public static ClassFileLocator ofRuntimeJar() throws IOException {
String javaHome = System.getProperty("java.home").replace('\\', '/');
File runtimeJar = null;
for (String location : RUNTIME_LOCATIONS) {
File candidate = new File(javaHome, location);
if (candidate.isFile()) {
runtimeJar = candidate;
break;
}
}
if (runtimeJar == null) {
throw new IllegalStateException("Runtime jar does not exist in " + javaHome + " for any of " + RUNTIME_LOCATIONS);
}
return of(runtimeJar);
}
@Override
public Resolution locate(String typeName) throws IOException {
ZipEntry zipEntry = jarFile.getEntry(typeName.replace('.', '/') + CLASS_FILE_EXTENSION);
if (zipEntry == null) {
return new Resolution.Illegal(typeName);
} else {
InputStream inputStream = jarFile.getInputStream(zipEntry);
try {
return new Resolution.Explicit(StreamDrainer.DEFAULT.drain(inputStream));
} finally {
inputStream.close();
}
}
}
@Override
public void close() throws IOException {
jarFile.close();
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.ForJarFile)) return false;
final ClassFileLocator.ForJarFile other = (ClassFileLocator.ForJarFile) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$jarFile = this.jarFile;
final java.lang.Object other$jarFile = other.jarFile;
if (this$jarFile == null ? other$jarFile != null : !this$jarFile.equals(other$jarFile)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.ForJarFile;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $jarFile = this.jarFile;
result = result * PRIME + ($jarFile == null ? 43 : $jarFile.hashCode());
return result;
}
}
/**
* A class file locator that locates classes within a Java <i>jmod</i> file. This class file locator should not be used
* for reading modular jar files for which {@link ForJarFile} is appropriate.
*/
class ForModuleFile implements ClassFileLocator {
/**
* The file extension of a modular Java package.
*/
private static final String JMOD_FILE_EXTENSION = ".jmod";
/**
* A list of potential locations of the boot path for different platforms.
*/
private static final List<String> BOOT_LOCATIONS = Arrays.asList("jmods", "../jmods");
/**
* The represented jmod file.
*/
private final ZipFile zipFile;
/**
* Creates a new class file locator for a jmod file.
*
* @param zipFile The represented jmod file.
*/
public ForModuleFile(ZipFile zipFile) {
this.zipFile = zipFile;
}
/**
* Creates a new class file locator for this VM's boot module path.
*
* @return A class file locator for this VM's boot module path.
* @throws IOException If an I/O error occurs.
*/
public static ClassFileLocator ofBootPath() throws IOException {
String javaHome = System.getProperty("java.home").replace('\\', '/');
File bootPath = null;
for (String location : BOOT_LOCATIONS) {
File candidate = new File(javaHome, location);
if (candidate.isDirectory()) {
bootPath = candidate;
break;
}
}
if (bootPath == null) {
throw new IllegalStateException("Boot modules do not exist in " + javaHome + " for any of " + BOOT_LOCATIONS);
}
return ofBootPath(bootPath);
}
/**
* Creates a new class file locator for a Java boot module path.
*
* @param bootPath The boot path folder.
* @return A class file locator for this VMs boot module path.
* @throws IOException If an I/O error occurs.
*/
public static ClassFileLocator ofBootPath(File bootPath) throws IOException {
File[] module = bootPath.listFiles();
if (module == null) {
return NoOp.INSTANCE;
}
List<ClassFileLocator> classFileLocators = new ArrayList<ClassFileLocator>(module.length);
for (File aModule : module) {
if (aModule.isFile()) {
classFileLocators.add(of(aModule));
}
}
return new Compound(classFileLocators);
}
/**
* <p>
* Resolves a class file locator for this VM's Java module path that reads class files directly from the file system.
* </p>
* <p>
* <b>Note</b>: The resulting class file locator does not include classes of the bootstrap class loader.
* </p>
*
* @return A class file locator for the class path.
* @throws IOException If an I/O exception occurs.
*/
public static ClassFileLocator ofModulePath() throws IOException {
String modulePath = System.getProperty("jdk.module.path");
return modulePath == null ? NoOp.INSTANCE : ofModulePath(modulePath);
}
/**
* <p>
* Resolves a class file locator for a Java module path that reads class files directly from the file system. All
* elements of the module path are resolved releatively to this VM's {@code user.dir}.
* </p>
* <p>
* <b>Note</b>: The resulting class file locator does not include classes of the bootstrap class loader.
* </p>
*
* @param modulePath The module path to scan with the elements separated by {@code path.separator}.
* @return A class file locator for the class path.
* @throws IOException If an I/O exception occurs.
*/
public static ClassFileLocator ofModulePath(String modulePath) throws IOException {
return ofModulePath(modulePath, System.getProperty("user.dir"));
}
/**
* <p>
* Resolves a class file locator for a Java module path that reads class files directly from the file system.
* </p>
* <p>
* <b>Note</b>: The resulting class file locator does not include classes of the bootstrap class loader.
* </p>
*
* @param modulePath The module path to scan with the elements separated by {@code path.separator}.
* @param baseFolder The relative location of the elements on the module path.
* @return A class file locator for the class path.
* @throws IOException If an I/O exception occurs.
*/
public static ClassFileLocator ofModulePath(String modulePath, String baseFolder) throws IOException {
List<ClassFileLocator> classFileLocators = new ArrayList<ClassFileLocator>();
for (String element : Pattern.compile(System.getProperty("path.separator"), Pattern.LITERAL).split(modulePath)) {
File file = new File(baseFolder, element);
if (file.isDirectory()) {
File[] module = file.listFiles();
if (module != null) {
for (File aModule : module) {
if (aModule.isDirectory()) {
classFileLocators.add(new ForFolder(aModule));
} else if (aModule.isFile()) {
classFileLocators.add(aModule.getName().endsWith(JMOD_FILE_EXTENSION) ? of(aModule) : ForJarFile.of(aModule));
}
}
}
} else if (file.isFile()) {
classFileLocators.add(file.getName().endsWith(JMOD_FILE_EXTENSION) ? of(file) : ForJarFile.of(file));
}
}
return new Compound(classFileLocators);
}
/**
* Returns a class file locator for the given module file.
*
* @param file The module file.
* @return A class file locator for the given module
* @throws IOException If an I/O error occurs.
*/
public static ClassFileLocator of(File file) throws IOException {
return new ForModuleFile(new ZipFile(file));
}
@Override
public Resolution locate(String typeName) throws IOException {
ZipEntry zipEntry = zipFile.getEntry("classes/" + typeName.replace('.', '/') + CLASS_FILE_EXTENSION);
if (zipEntry == null) {
return new Resolution.Illegal(typeName);
} else {
InputStream inputStream = zipFile.getInputStream(zipEntry);
try {
return new Resolution.Explicit(StreamDrainer.DEFAULT.drain(inputStream));
} finally {
inputStream.close();
}
}
}
@Override
public void close() throws IOException {
zipFile.close();
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.ForModuleFile)) return false;
final ClassFileLocator.ForModuleFile other = (ClassFileLocator.ForModuleFile) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$zipFile = this.zipFile;
final java.lang.Object other$zipFile = other.zipFile;
if (this$zipFile == null ? other$zipFile != null : !this$zipFile.equals(other$zipFile)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.ForModuleFile;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $zipFile = this.zipFile;
result = result * PRIME + ($zipFile == null ? 43 : $zipFile.hashCode());
return result;
}
}
/**
* A class file locator that finds files from a standardized Java folder structure with
* folders donating packages and class files being saved as {@code <classname>.class} files
* within their package folder.
*/
class ForFolder implements ClassFileLocator {
/**
* The base folder of the package structure.
*/
private final File folder;
/**
* Creates a new class file locator for a folder structure of class files.
*
* @param folder The base folder of the package structure.
*/
public ForFolder(File folder) {
this.folder = folder;
}
@Override
public Resolution locate(String typeName) throws IOException {
File file = new File(folder, typeName.replace('.', File.separatorChar) + CLASS_FILE_EXTENSION);
if (file.exists()) {
InputStream inputStream = new FileInputStream(file);
try {
return new Resolution.Explicit(StreamDrainer.DEFAULT.drain(inputStream));
} finally {
inputStream.close();
}
} else {
return new Resolution.Illegal(typeName);
}
}
@Override
public void close() throws IOException {
/* do nothing */
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.ForFolder)) return false;
final ClassFileLocator.ForFolder other = (ClassFileLocator.ForFolder) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$folder = this.folder;
final java.lang.Object other$folder = other.folder;
if (this$folder == null ? other$folder != null : !this$folder.equals(other$folder)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.ForFolder;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $folder = this.folder;
result = result * PRIME + ($folder == null ? 43 : $folder.hashCode());
return result;
}
}
/**
* A Java agent that allows the location of class files by emulating a retransformation. Note that this class file
* locator causes a class to be loaded in order to look up its class file. Also, this locator does deliberately not
* support the look-up of classes that represent lambda expressions.
*/
class AgentBased implements ClassFileLocator {
/**
* The name of the Byte Buddy {@code net.bytebuddy.agent.Installer} class.
*/
private static final String INSTALLER_TYPE = "net.bytebuddy.agent.Installer";
/**
* The name of the {@code net.bytebuddy.agent.Installer} getter for reading an installed {@link Instrumentation}.
*/
private static final String INSTRUMENTATION_GETTER = "getInstrumentation";
/**
* Indicator for access to a static member via reflection to make the code more readable.
*/
private static final Object STATIC_MEMBER = null;
/**
* The instrumentation instance to use for looking up the binary format of a type.
*/
private final Instrumentation instrumentation;
/**
* The delegate to load a class by its name.
*/
private final ClassLoadingDelegate classLoadingDelegate;
/**
* Creates an agent-based class file locator.
*
* @param instrumentation The instrumentation to be used.
* @param classLoader The class loader to read a class from.
*/
public AgentBased(Instrumentation instrumentation, ClassLoader classLoader) {
this(instrumentation, ClassLoadingDelegate.Default.of(classLoader));
}
/**
* Creates an agent-based class file locator.
*
* @param instrumentation The instrumentation to be used.
* @param classLoadingDelegate The delegate responsible for class loading.
*/
public AgentBased(Instrumentation instrumentation, ClassLoadingDelegate classLoadingDelegate) {
if (!instrumentation.isRetransformClassesSupported()) {
throw new IllegalArgumentException(instrumentation + " does not support retransformation");
}
this.instrumentation = instrumentation;
this.classLoadingDelegate = classLoadingDelegate;
}
/**
* Returns an agent-based class file locator for the given class loader and an already installed
* Byte Buddy-agent.
*
* @param classLoader The class loader that is expected to load the looked-up a class.
* @return A class file locator for the given class loader based on a Byte Buddy agent.
*/
public static ClassFileLocator fromInstalledAgent(ClassLoader classLoader) {
try {
return new AgentBased((Instrumentation) ClassLoader.getSystemClassLoader().loadClass(INSTALLER_TYPE).getMethod(INSTRUMENTATION_GETTER).invoke(STATIC_MEMBER), classLoader);
} catch (RuntimeException exception) {
throw exception;
} catch (Exception exception) {
throw new IllegalStateException("The Byte Buddy agent is not installed or not accessible", exception);
}
}
/**
* Returns a class file locator that is capable of locating a class file for the given type using the given instrumentation instance.
*
* @param instrumentation The instrumentation instance to query for a retransformation.
* @param type The locatable type which class loader is used as a fallback.
* @return A class file locator for locating the class file of the given type.
*/
public static ClassFileLocator of(Instrumentation instrumentation, Class<?> type) {
return new AgentBased(instrumentation, ClassLoadingDelegate.Explicit.of(type));
}
@Override
public Resolution locate(String typeName) {
try {
ExtractionClassFileTransformer classFileTransformer = new ExtractionClassFileTransformer(classLoadingDelegate.getClassLoader(), typeName);
instrumentation.addTransformer(classFileTransformer, true);
try {
instrumentation.retransformClasses(classLoadingDelegate.locate(typeName));
byte[] binaryRepresentation = classFileTransformer.getBinaryRepresentation();
return binaryRepresentation == null ? new Resolution.Illegal(typeName) : new Resolution.Explicit(binaryRepresentation);
} finally {
instrumentation.removeTransformer(classFileTransformer);
}
} catch (RuntimeException exception) {
throw exception;
} catch (Exception ignored) {
return new Resolution.Illegal(typeName);
}
}
@Override
public void close() throws IOException {
/* do nothing */
}
/**
* A delegate that is queried for loading a class.
*/
public interface ClassLoadingDelegate {
/**
* Loads a class by its name.
*
* @param name The name of the type.
* @return The class with the given name.
* @throws ClassNotFoundException If a class cannot be found.
*/
Class<?> locate(String name) throws ClassNotFoundException;
/**
* Returns the underlying class loader.
*
* @return The underlying class loader.
*/
ClassLoader getClassLoader();
/**
* A default implementation of a class loading delegate.
*/
class Default implements ClassLoadingDelegate {
/**
* The underlying class loader.
*/
protected final ClassLoader classLoader;
/**
* Creates a default class loading delegate.
*
* @param classLoader The class loader to be queried.
*/
protected Default(ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Creates a class loading delegate for the given class loader.
*
* @param classLoader The class loader for which to create a delegate.
* @return The class loading delegate for the provided class loader.
*/
public static ClassLoadingDelegate of(ClassLoader classLoader) {
return ForDelegatingClassLoader.isDelegating(classLoader) ? new ForDelegatingClassLoader(classLoader) : new Default(classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader);
}
@Override
public Class<?> locate(String name) throws ClassNotFoundException {
return classLoader.loadClass(name);
}
@Override
public ClassLoader getClassLoader() {
return classLoader;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.AgentBased.ClassLoadingDelegate.Default)) return false;
final ClassFileLocator.AgentBased.ClassLoadingDelegate.Default other = (ClassFileLocator.AgentBased.ClassLoadingDelegate.Default) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$classLoader = this.getClassLoader();
final java.lang.Object other$classLoader = other.getClassLoader();
if (this$classLoader == null ? other$classLoader != null : !this$classLoader.equals(other$classLoader)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.AgentBased.ClassLoadingDelegate.Default;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $classLoader = this.getClassLoader();
result = result * PRIME + ($classLoader == null ? 43 : $classLoader.hashCode());
return result;
}
}
/**
* A class loading delegate that accounts for a {@code sun.reflect.DelegatingClassLoader} which
* cannot load its own classes by name.
*/
class ForDelegatingClassLoader extends Default {
/**
* The name of the delegating class loader.
*/
private static final String DELEGATING_CLASS_LOADER_NAME = "sun.reflect.DelegatingClassLoader";
/**
* An index indicating the first element of a collection.
*/
private static final int ONLY = 0;
/**
* A dispatcher for extracting a class loader's loaded classes.
*/
private static final Dispatcher.Initializable DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE);
/**
* Creates a class loading delegate for a delegating class loader.
*
* @param classLoader The delegating class loader.
*/
protected ForDelegatingClassLoader(ClassLoader classLoader) {
super(classLoader);
}
/**
* Checks if a class loader is a delegating class loader.
*
* @param classLoader The class loader to inspect.
* @return {@code true} if the class loader is a delegating class loader.
*/
protected static boolean isDelegating(ClassLoader classLoader) {
return classLoader != null && classLoader.getClass().getName().equals(DELEGATING_CLASS_LOADER_NAME);
}
@Override
@SuppressWarnings("unchecked")
public Class<?> locate(String name) throws ClassNotFoundException {
Vector<Class<?>> classes;
try {
classes = DISPATCHER.initialize().extract(classLoader);
} catch (RuntimeException ignored) {
return super.locate(name);
}
if (classes.size() != 1) {
return super.locate(name);
}
Class<?> type = classes.get(ONLY);
return TypeDescription.ForLoadedType.getName(type).equals(name) ? type : super.locate(name);
}
/**
* Representation of a Java {@link java.lang.reflect.Field}.
*/
protected interface Dispatcher {
/**
* Reads the classes of the represented collection.
*
* @param classLoader The class loader to read from.
* @return The class loader's loaded classes.
*/
Vector<Class<?>> extract(ClassLoader classLoader);
/**
* An unitialized version of a dispatcher for extracting a class loader's loaded classes.
*/
interface Initializable {
/**
* Initializes the dispatcher.
*
* @return An initialized dispatcher.
*/
Dispatcher initialize();
}
/**
* An action for creating a dispatcher.
*/
enum CreationAction implements PrivilegedAction<Initializable> {
/**
* The singleton instance.
*/
INSTANCE;
@Override
public Initializable run() {
try {
return new Dispatcher.Resolved(ClassLoader.class.getDeclaredField("classes"));
} catch (Exception exception) {
return new Dispatcher.Unresolved(exception);
}
}
}
/**
* Represents a field that could be located.
*/
class Resolved implements Dispatcher, Initializable, PrivilegedAction<Dispatcher> {
/**
* The represented field.
*/
private final Field field;
/**
* Creates a new resolved field.
*
* @param field the represented field.l
*/
public Resolved(Field field) {
this.field = field;
}
@Override
public Dispatcher initialize() {
return AccessController.doPrivileged(this);
}
@Override
@SuppressWarnings("unchecked")
public Vector<Class<?>> extract(ClassLoader classLoader) {
try {
return (Vector<Class<?>>) field.get(classLoader);
} catch (IllegalAccessException exception) {
throw new IllegalStateException("Cannot access field", exception);
}
}
@Override
public Dispatcher run() {
field.setAccessible(true);
return this;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Resolved)) return false;
final ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Resolved other = (ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Resolved) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$field = this.field;
final java.lang.Object other$field = other.field;
if (this$field == null ? other$field != null : !this$field.equals(other$field)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Resolved;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $field = this.field;
result = result * PRIME + ($field == null ? 43 : $field.hashCode());
return result;
}
}
/**
* Represents a field that could not be located.
*/
class Unresolved implements Initializable {
/**
* The exception that occurred when attempting to locate the field.
*/
private final Exception exception;
/**
* Creates a representation of a non-resolved field.
*
* @param exception The exception that occurred when attempting to locate the field.
*/
public Unresolved(Exception exception) {
this.exception = exception;
}
@Override
public Dispatcher initialize() {
throw new IllegalStateException("Could not locate classes vector", exception);
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Unresolved)) return false;
final ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Unresolved other = (ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Unresolved) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$exception = this.exception;
final java.lang.Object other$exception = other.exception;
if (this$exception == null ? other$exception != null : !this$exception.equals(other$exception)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Unresolved;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $exception = this.exception;
result = result * PRIME + ($exception == null ? 43 : $exception.hashCode());
return result;
}
}
}
}
/**
* A class loading delegate that allows the location of explicitly registered classes that cannot
* be located by a class loader directly. This allows for locating classes that are loaded by
* an anonymous class loader which does not register its classes in a system dictionary.
*/
class Explicit implements ClassLoadingDelegate {
/**
* A class loading delegate that is queried for classes that are not registered explicitly.
*/
private final ClassLoadingDelegate fallbackDelegate;
/**
* The map of registered classes mapped by their name.
*/
private final Map<String, Class<?>> types;
/**
* Creates a new class loading delegate with a possibility of looking up explicitly
* registered classes.
*
* @param classLoader The class loader to be used for looking up classes.
* @param types A collection of classes that cannot be looked up explicitly.
*/
public Explicit(ClassLoader classLoader, Collection<? extends Class<?>> types) {
this(Default.of(classLoader), types);
}
/**
* Creates a new class loading delegate with a possibility of looking up explicitly
* registered classes.
*
* @param fallbackDelegate The class loading delegate to query for any class that is not
* registered explicitly.
* @param types A collection of classes that cannot be looked up explicitly.
*/
public Explicit(ClassLoadingDelegate fallbackDelegate, Collection<? extends Class<?>> types) {
this.fallbackDelegate = fallbackDelegate;
this.types = new HashMap<String, Class<?>>();
for (Class<?> type : types) {
this.types.put(TypeDescription.ForLoadedType.getName(type), type);
}
}
/**
* Creates an explicit class loading delegate for the given type.
*
* @param type The type that is explicitly locatable.
* @return A suitable class loading delegate.
*/
public static ClassLoadingDelegate of(Class<?> type) {
return new Explicit(type.getClassLoader(), Collections.singleton(type));
}
@Override
public Class<?> locate(String name) throws ClassNotFoundException {
Class<?> type = types.get(name);
return type == null ? fallbackDelegate.locate(name) : type;
}
@Override
public ClassLoader getClassLoader() {
return fallbackDelegate.getClassLoader();
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.AgentBased.ClassLoadingDelegate.Explicit)) return false;
final ClassFileLocator.AgentBased.ClassLoadingDelegate.Explicit other = (ClassFileLocator.AgentBased.ClassLoadingDelegate.Explicit) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$fallbackDelegate = this.fallbackDelegate;
final java.lang.Object other$fallbackDelegate = other.fallbackDelegate;
if (this$fallbackDelegate == null ? other$fallbackDelegate != null : !this$fallbackDelegate.equals(other$fallbackDelegate)) return false;
final java.lang.Object this$types = this.types;
final java.lang.Object other$types = other.types;
if (this$types == null ? other$types != null : !this$types.equals(other$types)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.AgentBased.ClassLoadingDelegate.Explicit;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $fallbackDelegate = this.fallbackDelegate;
result = result * PRIME + ($fallbackDelegate == null ? 43 : $fallbackDelegate.hashCode());
final java.lang.Object $types = this.types;
result = result * PRIME + ($types == null ? 43 : $types.hashCode());
return result;
}
}
}
/**
* A non-operational class file transformer that remembers the binary format of a given class.
*/
protected static class ExtractionClassFileTransformer implements ClassFileTransformer {
/**
* An indicator that an attempted class file transformation did not alter the handed class file.
*/
private static final byte[] DO_NOT_TRANSFORM = null;
/**
* The class loader that is expected to have loaded the looked-up a class.
*/
private final ClassLoader classLoader;
/**
* The name of the type to look up.
*/
private final String typeName;
/**
* The binary representation of the looked-up class.
*/
private volatile byte[] binaryRepresentation;
/**
* Creates a class file transformer for the purpose of extraction.
*
* @param classLoader The class loader that is expected to have loaded the looked-up a class.
* @param typeName The name of the type to look up.
*/
protected ExtractionClassFileTransformer(ClassLoader classLoader, String typeName) {
this.classLoader = classLoader;
this.typeName = typeName;
}
@Override
public byte[] transform(ClassLoader classLoader, String internalName, Class<?> redefinedType, ProtectionDomain protectionDomain, byte[] binaryRepresentation) {
if (internalName != null && ElementMatchers.isChildOf(this.classLoader).matches(classLoader) && typeName.equals(internalName.replace('/', '.'))) {
this.binaryRepresentation = binaryRepresentation.clone();
}
return DO_NOT_TRANSFORM;
}
/**
* Returns the binary representation of the class file that was looked up. The returned array must never be modified.
*
* @return The binary representation of the class file or {@code null} if no such class file could
* be located.
*/
protected byte[] getBinaryRepresentation() {
return binaryRepresentation;
}
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.AgentBased)) return false;
final ClassFileLocator.AgentBased other = (ClassFileLocator.AgentBased) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$instrumentation = this.instrumentation;
final java.lang.Object other$instrumentation = other.instrumentation;
if (this$instrumentation == null ? other$instrumentation != null : !this$instrumentation.equals(other$instrumentation)) return false;
final java.lang.Object this$classLoadingDelegate = this.classLoadingDelegate;
final java.lang.Object other$classLoadingDelegate = other.classLoadingDelegate;
if (this$classLoadingDelegate == null ? other$classLoadingDelegate != null : !this$classLoadingDelegate.equals(other$classLoadingDelegate)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.AgentBased;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $instrumentation = this.instrumentation;
result = result * PRIME + ($instrumentation == null ? 43 : $instrumentation.hashCode());
final java.lang.Object $classLoadingDelegate = this.classLoadingDelegate;
result = result * PRIME + ($classLoadingDelegate == null ? 43 : $classLoadingDelegate.hashCode());
return result;
}
}
/**
* A class file locator that discriminates by a type's package.
*/
class PackageDiscriminating implements ClassFileLocator {
/**
* A mapping of package names to class file locators.
*/
private final Map<String, ClassFileLocator> classFileLocators;
/**
* Creates a new package-discriminating class file locator.
*
* @param classFileLocators A mapping of package names to class file locators where an empty string donates the default package.
*/
public PackageDiscriminating(Map<String, ClassFileLocator> classFileLocators) {
this.classFileLocators = classFileLocators;
}
@Override
public Resolution locate(String typeName) throws IOException {
int packageIndex = typeName.lastIndexOf('.');
ClassFileLocator classFileLocator = classFileLocators.get(packageIndex == -1 ? NamedElement.EMPTY_NAME : typeName.substring(0, packageIndex));
return classFileLocator == null ? new Resolution.Illegal(typeName) : classFileLocator.locate(typeName);
}
@Override
public void close() throws IOException {
for (ClassFileLocator classFileLocator : classFileLocators.values()) {
classFileLocator.close();
}
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.PackageDiscriminating)) return false;
final ClassFileLocator.PackageDiscriminating other = (ClassFileLocator.PackageDiscriminating) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$classFileLocators = this.classFileLocators;
final java.lang.Object other$classFileLocators = other.classFileLocators;
if (this$classFileLocators == null ? other$classFileLocators != null : !this$classFileLocators.equals(other$classFileLocators)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.PackageDiscriminating;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $classFileLocators = this.classFileLocators;
result = result * PRIME + ($classFileLocators == null ? 43 : $classFileLocators.hashCode());
return result;
}
}
/**
* A compound {@link ClassFileLocator} that chains several locators.
* Any class file locator is queried in the supplied order until one locator is able to provide an input
* stream of the class file.
*/
class Compound implements ClassFileLocator, Closeable {
/**
* The {@link ClassFileLocator}s which are represented by this compound
* class file locator in the order of their application.
*/
private final List<ClassFileLocator> classFileLocators;
/**
* Creates a new compound class file locator.
*
* @param classFileLocator The {@link ClassFileLocator}s to be
* represented by this compound class file locator in the order of their application.
*/
public Compound(ClassFileLocator... classFileLocator) {
this(Arrays.asList(classFileLocator));
}
/**
* Creates a new compound class file locator.
*
* @param classFileLocators The {@link ClassFileLocator}s to be represented by this compound class file locator in
* the order of their application.
*/
public Compound(List<? extends ClassFileLocator> classFileLocators) {
this.classFileLocators = new ArrayList<ClassFileLocator>();
for (ClassFileLocator classFileLocator : classFileLocators) {
if (classFileLocator instanceof Compound) {
this.classFileLocators.addAll(((Compound) classFileLocator).classFileLocators);
} else if (!(classFileLocator instanceof NoOp)) {
this.classFileLocators.add(classFileLocator);
}
}
}
@Override
public Resolution locate(String typeName) throws IOException {
for (ClassFileLocator classFileLocator : classFileLocators) {
Resolution resolution = classFileLocator.locate(typeName);
if (resolution.isResolved()) {
return resolution;
}
}
return new Resolution.Illegal(typeName);
}
@Override
public void close() throws IOException {
for (ClassFileLocator classFileLocator : classFileLocators) {
classFileLocator.close();
}
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ClassFileLocator.Compound)) return false;
final ClassFileLocator.Compound other = (ClassFileLocator.Compound) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$classFileLocators = this.classFileLocators;
final java.lang.Object other$classFileLocators = other.classFileLocators;
if (this$classFileLocators == null ? other$classFileLocators != null : !this$classFileLocators.equals(other$classFileLocators)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof ClassFileLocator.Compound;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@javax.annotation.Generated("lombok")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $classFileLocators = this.classFileLocators;
result = result * PRIME + ($classFileLocators == null ? 43 : $classFileLocators.hashCode());
return result;
}
}
}