/*
 * Copyright 2014 - 2019 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.build;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.inline.MethodNameTransformer;
import net.bytebuddy.implementation.LoadedTypeInitializer;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.pool.TypePool;
import net.bytebuddy.utility.CompoundList;

import java.io.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

import static net.bytebuddy.matcher.ElementMatchers.none;

A plugin that allows for the application of Byte Buddy transformations during a build process. This plugin's transformation is applied to any type matching this plugin's type matcher. Plugin types must be public, non-abstract and must declare a public default constructor to work.
/** * A plugin that allows for the application of Byte Buddy transformations during a build process. This plugin's * transformation is applied to any type matching this plugin's type matcher. Plugin types must be public, * non-abstract and must declare a public default constructor to work. */
public interface Plugin extends ElementMatcher<TypeDescription>, Closeable {
Applies this plugin.
Params:
  • builder – The builder to use as a basis for the applied transformation.
  • typeDescription – The type being transformed.
  • classFileLocator – A class file locator that can locate other types in the scope of the project.
Returns:The supplied builder with additional transformations registered.
/** * Applies this plugin. * * @param builder The builder to use as a basis for the applied transformation. * @param typeDescription The type being transformed. * @param classFileLocator A class file locator that can locate other types in the scope of the project. * @return The supplied builder with additional transformations registered. */
DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator);
A factory for providing a build plugin.
/** * A factory for providing a build plugin. */
interface Factory {
Returns a plugin that can be used for a transformation and which is subsequently closed.
Returns:The plugin to use for type transformations.
/** * Returns a plugin that can be used for a transformation and which is subsequently closed. * * @return The plugin to use for type transformations. */
Plugin make();
A simple factory that returns a preconstructed plugin instance..
/** * A simple factory that returns a preconstructed plugin instance.. */
@HashCodeAndEqualsPlugin.Enhance class Simple implements Factory {
The plugin to provide.
/** * The plugin to provide. */
private final Plugin plugin;
Creates a simple plugin factory.
Params:
  • plugin – The plugin to provide.
/** * Creates a simple plugin factory. * * @param plugin The plugin to provide. */
public Simple(Plugin plugin) { this.plugin = plugin; }
{@inheritDoc}
/** * {@inheritDoc} */
public Plugin make() { return plugin; } }
A plugin factory that uses reflection for instantiating a plugin.
/** * A plugin factory that uses reflection for instantiating a plugin. */
@HashCodeAndEqualsPlugin.Enhance class UsingReflection implements Factory {
The plugin type.
/** * The plugin type. */
private final Class<? extends Plugin> type;
A list of argument providers that can be used for instantiating the plugin.
/** * A list of argument providers that can be used for instantiating the plugin. */
private final List<ArgumentResolver> argumentResolvers;
Creates a plugin factory that uses reflection for creating a plugin.
Params:
  • type – The plugin type.
/** * Creates a plugin factory that uses reflection for creating a plugin. * * @param type The plugin type. */
public UsingReflection(Class<? extends Plugin> type) { this(type, Collections.<ArgumentResolver>emptyList()); }
Creates a plugin factory that uses reflection for creating a plugin.
Params:
  • type – The plugin type.
  • argumentResolvers – A list of argument providers that can be used for instantiating the plugin.
/** * Creates a plugin factory that uses reflection for creating a plugin. * * @param type The plugin type. * @param argumentResolvers A list of argument providers that can be used for instantiating the plugin. */
protected UsingReflection(Class<? extends Plugin> type, List<ArgumentResolver> argumentResolvers) { this.type = type; this.argumentResolvers = argumentResolvers; }
Appends the supplied argument resolvers.
Params:
  • argumentResolver – A list of argument providers that can be used for instantiating the plugin.
Returns:A new plugin factory that uses reflection for creating a plugin that also uses the supplied argument resolvers.
/** * Appends the supplied argument resolvers. * * @param argumentResolver A list of argument providers that can be used for instantiating the plugin. * @return A new plugin factory that uses reflection for creating a plugin that also uses the supplied argument resolvers. */
public UsingReflection with(ArgumentResolver... argumentResolver) { return with(Arrays.asList(argumentResolver)); }
Appends the supplied argument resolvers.
Params:
  • argumentResolvers – A list of argument providers that can be used for instantiating the plugin.
Returns:A new plugin factory that uses reflection for creating a plugin that also uses the supplied argument resolvers.
/** * Appends the supplied argument resolvers. * * @param argumentResolvers A list of argument providers that can be used for instantiating the plugin. * @return A new plugin factory that uses reflection for creating a plugin that also uses the supplied argument resolvers. */
public UsingReflection with(List<? extends ArgumentResolver> argumentResolvers) { return new UsingReflection(type, CompoundList.of(argumentResolvers, this.argumentResolvers)); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressWarnings("unchecked") public Plugin make() { Instantiator instantiator = new Instantiator.Unresolved(type); candidates: for (Constructor<?> constructor : type.getConstructors()) { if (!constructor.isSynthetic()) { List<Object> arguments = new ArrayList<Object>(constructor.getParameterTypes().length); int index = 0; for (Class<?> type : constructor.getParameterTypes()) { boolean resolved = false; for (ArgumentResolver argumentResolver : argumentResolvers) { ArgumentResolver.Resolution resolution = argumentResolver.resolve(index, type); if (resolution.isResolved()) { arguments.add(resolution.getArgument()); resolved = true; break; } } if (resolved) { index += 1; } else { break candidates; } } instantiator = instantiator.replaceBy(new Instantiator.Resolved((Constructor<? extends Plugin>) constructor, arguments)); } } return instantiator.instantiate(); }
An instantiator is responsible for invoking a plugin constructor reflectively.
/** * An instantiator is responsible for invoking a plugin constructor reflectively. */
protected interface Instantiator {
Returns either this instantiator or the supplied instantiator, depending on the instances' states.
Params:
  • instantiator – The alternative instantiator.
Returns:The dominant instantiator.
/** * Returns either this instantiator or the supplied instantiator, depending on the instances' states. * * @param instantiator The alternative instantiator. * @return The dominant instantiator. */
Instantiator replaceBy(Resolved instantiator);
Instantiates the represented plugin.
Returns:The instantiated plugin.
/** * Instantiates the represented plugin. * * @return The instantiated plugin. */
Plugin instantiate();
An instantiator that is not resolved for creating an instance.
/** * An instantiator that is not resolved for creating an instance. */
@HashCodeAndEqualsPlugin.Enhance class Unresolved implements Instantiator {
The type for which no constructor was yet resolved.
/** * The type for which no constructor was yet resolved. */
private final Class<? extends Plugin> type;
Creates a new unresolved constructor.
Params:
  • type – The type for which no constructor was yet resolved.
/** * Creates a new unresolved constructor. * * @param type The type for which no constructor was yet resolved. */
protected Unresolved(Class<? extends Plugin> type) { this.type = type; }
{@inheritDoc}
/** * {@inheritDoc} */
public Instantiator replaceBy(Resolved instantiator) { return instantiator; }
{@inheritDoc}
/** * {@inheritDoc} */
public Plugin instantiate() { throw new IllegalStateException("No constructor available for " + type); } }
An instantiator that is resolved for a given constructor with arguments.
/** * An instantiator that is resolved for a given constructor with arguments. */
@HashCodeAndEqualsPlugin.Enhance class Resolved implements Instantiator {
The represented constructor.
/** * The represented constructor. */
private final Constructor<? extends Plugin> constructor;
The constructor arguments.
/** * The constructor arguments. */
private final List<?> arguments;
Creates a new resolved constructor.
Params:
  • constructor – The represented constructor.
  • arguments – The constructor arguments.
/** * Creates a new resolved constructor. * * @param constructor The represented constructor. * @param arguments The constructor arguments. */
protected Resolved(Constructor<? extends Plugin> constructor, List<?> arguments) { this.constructor = constructor; this.arguments = arguments; }
{@inheritDoc}
/** * {@inheritDoc} */
public Instantiator replaceBy(Resolved instantiator) { Priority left = constructor.getAnnotation(Priority.class), right = instantiator.constructor.getAnnotation(Priority.class); int leftPriority = left == null ? Priority.DEFAULT : left.value(), rightPriority = right == null ? Priority.DEFAULT : right.value(); if (leftPriority > rightPriority) { return this; } else if (leftPriority < rightPriority) { return instantiator; } else { throw new IllegalStateException("Ambiguous constructors " + constructor + " and " + instantiator.constructor); } }
{@inheritDoc}
/** * {@inheritDoc} */
public Plugin instantiate() { try { return constructor.newInstance(arguments.toArray(new Object[0])); } catch (InstantiationException exception) { throw new IllegalStateException("Failed to instantiate plugin via " + constructor, exception); } catch (IllegalAccessException exception) { throw new IllegalStateException("Failed to access " + constructor, exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error during construction of" + constructor, exception.getCause()); } } } }
Indicates that a constructor should be treated with a given priority if several constructors can be resolved.
/** * Indicates that a constructor should be treated with a given priority if several constructors can be resolved. */
@Documented @Target(ElementType.CONSTRUCTOR) @Retention(RetentionPolicy.RUNTIME) public @interface Priority {
The default priority that is assumed for non-annotated constructors.
/** * The default priority that is assumed for non-annotated constructors. */
int DEFAULT = 0;
Indicates the priority of the annotated constructor.
Returns:The priority of the annotated constructor.
/** * Indicates the priority of the annotated constructor. * * @return The priority of the annotated constructor. */
int value(); }
Allows to resolve arguments for a Plugin constructor.
/** * Allows to resolve arguments for a {@link Plugin} constructor. */
public interface ArgumentResolver {
Attempts the resolution of an argument for a given parameter.
Params:
  • index – The parameter's index.
  • type – The parameter's type.
Returns:The resolution for the parameter.
/** * Attempts the resolution of an argument for a given parameter. * * @param index The parameter's index. * @param type The parameter's type. * @return The resolution for the parameter. */
Resolution resolve(int index, Class<?> type);
A resolution provided by an argument provider.
/** * A resolution provided by an argument provider. */
interface Resolution {
Returns true if the represented argument is resolved successfully.
Returns:true if the represented argument is resolved successfully.
/** * Returns {@code true} if the represented argument is resolved successfully. * * @return {@code true} if the represented argument is resolved successfully. */
boolean isResolved();
Returns the resolved argument if the resolution was successful.
Returns:The resolved argument if the resolution was successful.
/** * Returns the resolved argument if the resolution was successful. * * @return The resolved argument if the resolution was successful. */
Object getArgument();
Represents an unresolved argument resolution.
/** * Represents an unresolved argument resolution. */
enum Unresolved implements Resolution {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isResolved() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
public Object getArgument() { throw new IllegalStateException("Cannot get the argument for an unresolved parameter"); } }
Represents a resolved argument resolution.
/** * Represents a resolved argument resolution. */
@HashCodeAndEqualsPlugin.Enhance class Resolved implements Resolution {
The resolved argument which might be null.
/** * The resolved argument which might be {@code null}. */
@HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY) private final Object argument;
Creates a resolved argument resolution.
Params:
  • argument – The resolved argument which might be null.
/** * Creates a resolved argument resolution. * * @param argument The resolved argument which might be {@code null}. */
public Resolved(Object argument) { this.argument = argument; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isResolved() { return true; }
{@inheritDoc}
/** * {@inheritDoc} */
public Object getArgument() { return argument; } } }
An argument resolver that never resolves an argument.
/** * An argument resolver that never resolves an argument. */
enum NoOp implements ArgumentResolver {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public Resolution resolve(int index, Class<?> type) { return Resolution.Unresolved.INSTANCE; } }
An argument resolver that resolves parameters for a given type.
Type parameters:
  • <T> – The type being resolved.
/** * An argument resolver that resolves parameters for a given type. * * @param <T> The type being resolved. */
@HashCodeAndEqualsPlugin.Enhance class ForType<T> implements ArgumentResolver {
The type being resolved.
/** * The type being resolved. */
private final Class<? extends T> type;
The instance to resolve for the represented type.
/** * The instance to resolve for the represented type. */
private final T value;
Creates a new argument resolver for a given type.
Params:
  • type – The type being resolved.
  • value – The instance to resolve for the represented type.
/** * Creates a new argument resolver for a given type. * * @param type The type being resolved. * @param value The instance to resolve for the represented type. */
protected ForType(Class<? extends T> type, T value) { this.type = type; this.value = value; }
Creates an argument resolver for a given type.
Params:
  • type – The type being resolved.
  • value – The instance to resolve for the represented type.
Type parameters:
  • <S> – The type being resolved.
Returns:An appropriate argument resolver.
/** * Creates an argument resolver for a given type. * * @param type The type being resolved. * @param value The instance to resolve for the represented type. * @param <S> The type being resolved. * @return An appropriate argument resolver. */
public static <S> ArgumentResolver of(Class<? extends S> type, S value) { return new ForType<S>(type, value); }
{@inheritDoc}
/** * {@inheritDoc} */
public Resolution resolve(int index, Class<?> type) { return type == this.type ? new Resolution.Resolved(value) : Resolution.Unresolved.INSTANCE; } }
An argument resolver that resolves an argument for a specific parameter index.
/** * An argument resolver that resolves an argument for a specific parameter index. */
@HashCodeAndEqualsPlugin.Enhance class ForIndex implements ArgumentResolver {
A mapping of primitive types to their wrapper types.
/** * A mapping of primitive types to their wrapper types. */
private static final Map<Class<?>, Class<?>> WRAPPER_TYPES; /* * Creates the primitive to wrapper type mapping. */ static { WRAPPER_TYPES = new HashMap<Class<?>, Class<?>>(); WRAPPER_TYPES.put(boolean.class, Boolean.class); WRAPPER_TYPES.put(byte.class, Byte.class); WRAPPER_TYPES.put(short.class, Short.class); WRAPPER_TYPES.put(char.class, Character.class); WRAPPER_TYPES.put(int.class, Integer.class); WRAPPER_TYPES.put(long.class, Long.class); WRAPPER_TYPES.put(float.class, Float.class); WRAPPER_TYPES.put(double.class, Double.class); }
The index of the parameter to resolve.
/** * The index of the parameter to resolve. */
private final int index;
The value to resolve for the represented index.
/** * The value to resolve for the represented index. */
private final Object value;
Creates an argument resolver for a given index.
Params:
  • index – The index of the parameter to resolve.
  • value – The value to resolve for the represented index.
/** * Creates an argument resolver for a given index. * * @param index The index of the parameter to resolve. * @param value The value to resolve for the represented index. */
public ForIndex(int index, Object value) { this.index = index; this.value = value; }
{@inheritDoc}
/** * {@inheritDoc} */
public Resolution resolve(int index, Class<?> type) { if (this.index != index) { return Resolution.Unresolved.INSTANCE; } else if (type.isPrimitive()) { return WRAPPER_TYPES.get(type).isInstance(value) ? new Resolution.Resolved(value) : Resolution.Unresolved.INSTANCE; } else { return value == null || type.isInstance(value) ? new Resolution.Resolved(value) : Resolution.Unresolved.INSTANCE; } }
An argument resolver that resolves an argument for a specific parameter index by attempting a conversion via invoking a static valueOf method on the target type, if it exists. As an exception, the char and Character types are resolved if the string value represents a single character.
/** * An argument resolver that resolves an argument for a specific parameter index by attempting a conversion via * invoking a static {@code valueOf} method on the target type, if it exists. As an exception, the {@code char} * and {@link Character} types are resolved if the string value represents a single character. */
@HashCodeAndEqualsPlugin.Enhance public static class WithDynamicType implements ArgumentResolver {
The index of the parameter to resolve.
/** * The index of the parameter to resolve. */
private final int index;
A string representation of the supplied value.
/** * A string representation of the supplied value. */
private final String value;
Creates an argument resolver for a specific parameter index and attempts a dynamic resolution.
Params:
  • index – The index of the parameter to resolve.
  • value – A string representation of the supplied value.
/** * Creates an argument resolver for a specific parameter index and attempts a dynamic resolution. * * @param index The index of the parameter to resolve. * @param value A string representation of the supplied value. */
public WithDynamicType(int index, String value) { this.index = index; this.value = value; }
{@inheritDoc}
/** * {@inheritDoc} */
public Resolution resolve(int index, Class<?> type) { if (this.index != index) { return Resolution.Unresolved.INSTANCE; } else if (type == char.class || type == Character.class) { return value.length() == 1 ? new Resolution.Resolved(value.charAt(0)) : Resolution.Unresolved.INSTANCE; } else if (type == String.class) { return new Resolution.Resolved(value); } else if (type.isPrimitive()) { type = WRAPPER_TYPES.get(type); } try { Method valueOf = type.getMethod("valueOf", String.class); return Modifier.isStatic(valueOf.getModifiers()) && type.isAssignableFrom(valueOf.getReturnType()) ? new Resolution.Resolved(valueOf.invoke(null, value)) : Resolution.Unresolved.INSTANCE; } catch (IllegalAccessException exception) { throw new IllegalStateException(exception); } catch (InvocationTargetException exception) { throw new IllegalStateException(exception.getCause()); } catch (NoSuchMethodException ignored) { return Resolution.Unresolved.INSTANCE; } } } } } } }
A plugin engine allows the application of one or more plugins on class files found at a Source which are then transferred and consumed by a Target.
/** * A plugin engine allows the application of one or more plugins on class files found at a {@link Source} which are * then transferred and consumed by a {@link Target}. */
interface Engine {
The class file extension.
/** * The class file extension. */
String CLASS_FILE_EXTENSION = ".class";
Defines a new Byte Buddy instance for usage for type creation.
Params:
  • byteBuddy – The Byte Buddy instance to use.
Returns:A new plugin engine that is equal to this engine but uses the supplied Byte Buddy instance.
/** * Defines a new Byte Buddy instance for usage for type creation. * * @param byteBuddy The Byte Buddy instance to use. * @return A new plugin engine that is equal to this engine but uses the supplied Byte Buddy instance. */
Engine with(ByteBuddy byteBuddy);
Defines a new type strategy which determines the transformation mode for any instrumented type.
Params:
  • typeStrategy – The type stategy to use.
Returns:A new plugin engine that is equal to this engine but uses the supplied type strategy.
/** * Defines a new type strategy which determines the transformation mode for any instrumented type. * * @param typeStrategy The type stategy to use. * @return A new plugin engine that is equal to this engine but uses the supplied type strategy. */
Engine with(TypeStrategy typeStrategy);
Defines a new pool strategy that determines how types are being described.
Params:
  • poolStrategy – The pool strategy to use.
Returns:A new plugin engine that is equal to this engine but uses the supplied pool strategy.
/** * Defines a new pool strategy that determines how types are being described. * * @param poolStrategy The pool strategy to use. * @return A new plugin engine that is equal to this engine but uses the supplied pool strategy. */
Engine with(PoolStrategy poolStrategy);
Appends the supplied class file locator to be queried for class files additionally to any previously registered class file locators.
Params:
  • classFileLocator – The class file locator to append.
Returns:A new plugin engine that is equal to this engine but with the supplied class file locator being appended.
/** * Appends the supplied class file locator to be queried for class files additionally to any previously registered * class file locators. * * @param classFileLocator The class file locator to append. * @return A new plugin engine that is equal to this engine but with the supplied class file locator being appended. */
Engine with(ClassFileLocator classFileLocator);
Appends the supplied listener to this engine.
Params:
  • listener – The listener to append.
Returns:A new plugin engine that is equal to this engine but with the supplied listener being appended.
/** * Appends the supplied listener to this engine. * * @param listener The listener to append. * @return A new plugin engine that is equal to this engine but with the supplied listener being appended. */
Engine with(Listener listener);
Replaces the error handlers of this plugin engine without applying any error handlers.
Returns:A new plugin engine that is equal to this engine but without any error handlers being registered.
/** * Replaces the error handlers of this plugin engine without applying any error handlers. * * @return A new plugin engine that is equal to this engine but without any error handlers being registered. */
Engine withoutErrorHandlers();
Replaces the error handlers of this plugin engine with the supplied error handlers.
Params:
  • errorHandler – The error handlers to apply.
Returns:A new plugin engine that is equal to this engine but with only the supplied error handlers being applied.
/** * Replaces the error handlers of this plugin engine with the supplied error handlers. * * @param errorHandler The error handlers to apply. * @return A new plugin engine that is equal to this engine but with only the supplied error handlers being applied. */
Engine withErrorHandlers(ErrorHandler... errorHandler);
Replaces the error handlers of this plugin engine with the supplied error handlers.
Params:
  • errorHandlers – The error handlers to apply.
Returns:A new plugin engine that is equal to this engine but with only the supplied error handlers being applied.
/** * Replaces the error handlers of this plugin engine with the supplied error handlers. * * @param errorHandlers The error handlers to apply. * @return A new plugin engine that is equal to this engine but with only the supplied error handlers being applied. */
Engine withErrorHandlers(List<? extends ErrorHandler> errorHandlers);
Ignores all types that are matched by this matcher or any previously registered ignore matcher.
Params:
  • matcher – The ignore matcher to append.
Returns:A new plugin engine that is equal to this engine but which ignores any type that is matched by the supplied matcher.
/** * Ignores all types that are matched by this matcher or any previously registered ignore matcher. * * @param matcher The ignore matcher to append. * @return A new plugin engine that is equal to this engine but which ignores any type that is matched by the supplied matcher. */
Engine ignore(ElementMatcher<? super TypeDescription> matcher);
Applies this plugin engine onto a given source and target.
Params:
  • source – The source which is treated as a folder or a jar file, if a folder does not exist.
  • target – The target which is treated as a folder or a jar file, if a folder does not exist.
  • factory – A list of plugin factories to a apply.
Throws:
Returns:A summary of the applied transformation.
/** * Applies this plugin engine onto a given source and target. * * @param source The source which is treated as a folder or a jar file, if a folder does not exist. * @param target The target which is treated as a folder or a jar file, if a folder does not exist. * @param factory A list of plugin factories to a apply. * @return A summary of the applied transformation. * @throws IOException If an I/O error occurs. */
Summary apply(File source, File target, Plugin.Factory... factory) throws IOException;
Applies this plugin engine onto a given source and target.
Params:
  • source – The source which is treated as a folder or a jar file, if a folder does not exist.
  • target – The target which is treated as a folder or a jar file, if a folder does not exist.
  • factories – A list of plugin factories to a apply.
Throws:
Returns:A summary of the applied transformation.
/** * Applies this plugin engine onto a given source and target. * * @param source The source which is treated as a folder or a jar file, if a folder does not exist. * @param target The target which is treated as a folder or a jar file, if a folder does not exist. * @param factories A list of plugin factories to a apply. * @return A summary of the applied transformation. * @throws IOException If an I/O error occurs. */
Summary apply(File source, File target, List<? extends Plugin.Factory> factories) throws IOException;
Applies this plugin engine onto a given source and target.
Params:
  • source – The source to use.
  • target – The target to use.
  • factory – A list of plugin factories to a apply.
Throws:
Returns:A summary of the applied transformation.
/** * Applies this plugin engine onto a given source and target. * * @param source The source to use. * @param target The target to use. * @param factory A list of plugin factories to a apply. * @return A summary of the applied transformation. * @throws IOException If an I/O error occurs. */
Summary apply(Source source, Target target, Plugin.Factory... factory) throws IOException;
Applies this plugin engine onto a given source and target.
Params:
  • source – The source to use.
  • target – The target to use.
  • factories – A list of plugin factories to a apply.
Throws:
Returns:A summary of the applied transformation.
/** * Applies this plugin engine onto a given source and target. * * @param source The source to use. * @param target The target to use. * @param factories A list of plugin factories to a apply. * @return A summary of the applied transformation. * @throws IOException If an I/O error occurs. */
Summary apply(Source source, Target target, List<? extends Plugin.Factory> factories) throws IOException;
A type strategy determines the transformation that is applied to a type description.
/** * A type strategy determines the transformation that is applied to a type description. */
interface TypeStrategy {
Creates a builder for a given type.
Params:
  • byteBuddy – The Byte Buddy instance to use.
  • typeDescription – The type being transformed.
  • classFileLocator – A class file locator for finding the type's class file.
Returns:A dynamic type builder for the provided type.
/** * Creates a builder for a given type. * * @param byteBuddy The Byte Buddy instance to use. * @param typeDescription The type being transformed. * @param classFileLocator A class file locator for finding the type's class file. * @return A dynamic type builder for the provided type. */
DynamicType.Builder<?> builder(ByteBuddy byteBuddy, TypeDescription typeDescription, ClassFileLocator classFileLocator);
Default implementations for type strategies.
/** * Default implementations for type strategies. */
enum Default implements TypeStrategy {
A type strategy that redefines a type's methods.
/** * A type strategy that redefines a type's methods. */
REDEFINE {
{@inheritDoc}
/** * {@inheritDoc} */
public DynamicType.Builder<?> builder(ByteBuddy byteBuddy, TypeDescription typeDescription, ClassFileLocator classFileLocator) { return byteBuddy.redefine(typeDescription, classFileLocator); } },
A type strategy that rebases a type's methods.
/** * A type strategy that rebases a type's methods. */
REBASE {
{@inheritDoc}
/** * {@inheritDoc} */
public DynamicType.Builder<?> builder(ByteBuddy byteBuddy, TypeDescription typeDescription, ClassFileLocator classFileLocator) { return byteBuddy.rebase(typeDescription, classFileLocator); } },
A type strategy that decorates a type.
/** * A type strategy that decorates a type. */
DECORATE {
{@inheritDoc}
/** * {@inheritDoc} */
public DynamicType.Builder<?> builder(ByteBuddy byteBuddy, TypeDescription typeDescription, ClassFileLocator classFileLocator) { return byteBuddy.decorate(typeDescription, classFileLocator); } } }
A type strategy that represents a given EntryPoint for a build tool.
/** * A type strategy that represents a given {@link EntryPoint} for a build tool. */
@HashCodeAndEqualsPlugin.Enhance class ForEntryPoint implements TypeStrategy {
The represented entry point.
/** * The represented entry point. */
private final EntryPoint entryPoint;
A method name transformer to use for rebasements.
/** * A method name transformer to use for rebasements. */
private final MethodNameTransformer methodNameTransformer;
Creates a new type stratrgy for an entry point.
Params:
  • entryPoint – The represented entry point.
  • methodNameTransformer – A method name transformer to use for rebasements.
/** * Creates a new type stratrgy for an entry point. * * @param entryPoint The represented entry point. * @param methodNameTransformer A method name transformer to use for rebasements. */
public ForEntryPoint(EntryPoint entryPoint, MethodNameTransformer methodNameTransformer) { this.entryPoint = entryPoint; this.methodNameTransformer = methodNameTransformer; }
{@inheritDoc}
/** * {@inheritDoc} */
public DynamicType.Builder<?> builder(ByteBuddy byteBuddy, TypeDescription typeDescription, ClassFileLocator classFileLocator) { return entryPoint.transform(typeDescription, byteBuddy, classFileLocator, methodNameTransformer); } } }
A pool strategy determines the creation of a TypePool for a plugin engine application.
/** * A pool strategy determines the creation of a {@link TypePool} for a plugin engine application. */
interface PoolStrategy {
Creates a type pool.
Params:
  • classFileLocator – The class file locator to use.
Returns:An approptiate type pool.
/** * Creates a type pool. * * @param classFileLocator The class file locator to use. * @return An approptiate type pool. */
TypePool typePool(ClassFileLocator classFileLocator);
A default implementation of a pool strategy where type descriptions are resolved lazily.
/** * A default implementation of a pool strategy where type descriptions are resolved lazily. */
enum Default implements PoolStrategy {
Enables faster class file parsing that does not process debug information of a class file.
/** * Enables faster class file parsing that does not process debug information of a class file. */
FAST(TypePool.Default.ReaderMode.FAST),
Enables extended class file parsing that extracts parameter names from debug information, if available.
/** * Enables extended class file parsing that extracts parameter names from debug information, if available. */
EXTENDED(TypePool.Default.ReaderMode.EXTENDED);
This strategy's reader mode.
/** * This strategy's reader mode. */
private final TypePool.Default.ReaderMode readerMode;
Creates a default pool strategy.
Params:
  • readerMode – This strategy's reader mode.
/** * Creates a default pool strategy. * * @param readerMode This strategy's reader mode. */
Default(TypePool.Default.ReaderMode readerMode) { this.readerMode = readerMode; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypePool typePool(ClassFileLocator classFileLocator) { return new TypePool.Default.WithLazyResolution(new TypePool.CacheProvider.Simple(), classFileLocator, readerMode, TypePool.ClassLoading.ofPlatformLoader()); } }
A pool strategy that resolves type descriptions eagerly. This can avoid additional overhead if the majority of types is assumed to be resolved eventually.
/** * A pool strategy that resolves type descriptions eagerly. This can avoid additional overhead if the * majority of types is assumed to be resolved eventually. */
enum Eager implements PoolStrategy {
Enables faster class file parsing that does not process debug information of a class file.
/** * Enables faster class file parsing that does not process debug information of a class file. */
FAST(TypePool.Default.ReaderMode.FAST),
Enables extended class file parsing that extracts parameter names from debug information, if available.
/** * Enables extended class file parsing that extracts parameter names from debug information, if available. */
EXTENDED(TypePool.Default.ReaderMode.EXTENDED);
This strategy's reader mode.
/** * This strategy's reader mode. */
private final TypePool.Default.ReaderMode readerMode;
Creates an eager pool strategy.
Params:
  • readerMode – This strategy's reader mode.
/** * Creates an eager pool strategy. * * @param readerMode This strategy's reader mode. */
Eager(TypePool.Default.ReaderMode readerMode) { this.readerMode = readerMode; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypePool typePool(ClassFileLocator classFileLocator) { return new TypePool.Default(new TypePool.CacheProvider.Simple(), classFileLocator, readerMode, TypePool.ClassLoading.ofPlatformLoader()); } } }
An error handler that is used during a plugin engine application.
/** * An error handler that is used during a plugin engine application. */
interface ErrorHandler {
Invoked if an error occured during a plugin's application on a given type.
Params:
  • typeDescription – The type being matched or transformed.
  • plugin – The plugin being applied.
  • throwable – The throwable that caused the error.
/** * Invoked if an error occured during a plugin's application on a given type. * * @param typeDescription The type being matched or transformed. * @param plugin The plugin being applied. * @param throwable The throwable that caused the error. */
void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable);
Invoked after the application of all plugins was attempted if at least one error occured during handling a given type.
Params:
  • typeDescription – The type being transformed.
  • throwables – The throwables that caused errors during the application.
/** * Invoked after the application of all plugins was attempted if at least one error occured during handling a given type. * * @param typeDescription The type being transformed. * @param throwables The throwables that caused errors during the application. */
void onError(TypeDescription typeDescription, List<Throwable> throwables);
Invoked at the end of the build if at least one type transformation failed.
Params:
  • throwables – A mapping of types that failed during transformation to the errors that were caught.
/** * Invoked at the end of the build if at least one type transformation failed. * * @param throwables A mapping of types that failed during transformation to the errors that were caught. */
void onError(Map<TypeDescription, List<Throwable>> throwables);
Invoked at the end of the build if a plugin could not be closed.
Params:
  • plugin – The plugin that could not be closed.
  • throwable – The error that was caused when the plugin was attempted to be closed.
/** * Invoked at the end of the build if a plugin could not be closed. * * @param plugin The plugin that could not be closed. * @param throwable The error that was caused when the plugin was attempted to be closed. */
void onError(Plugin plugin, Throwable throwable);
Invoked if a type transformation implied a live initializer.
Params:
  • typeDescription – The type that was transformed.
  • definingType – The type that implies the initializer which might be the type itself or an auxiliary type.
/** * Invoked if a type transformation implied a live initializer. * * @param typeDescription The type that was transformed. * @param definingType The type that implies the initializer which might be the type itself or an auxiliary type. */
void onLiveInitializer(TypeDescription typeDescription, TypeDescription definingType);
Invoked if a type could not be resolved.
Params:
  • typeName – The name of the unresolved type.
/** * Invoked if a type could not be resolved. * * @param typeName The name of the unresolved type. */
void onUnresolved(String typeName);
Invoked when a manifest was found or found missing.
Params:
  • manifest – The located manifest or null if no manifest was found.
/** * Invoked when a manifest was found or found missing. * * @param manifest The located manifest or {@code null} if no manifest was found. */
void onManifest(Manifest manifest);
Invoked if a resource that is not a class file is discovered.
Params:
  • name – The name of the discovered resource.
/** * Invoked if a resource that is not a class file is discovered. * * @param name The name of the discovered resource. */
void onResource(String name);
An implementation of an error handler that fails the plugin engine application.
/** * An implementation of an error handler that fails the plugin engine application. */
enum Failing implements ErrorHandler {
An error handler that fails the build immediatly on the first error.
/** * An error handler that fails the build immediatly on the first error. */
FAIL_FAST {
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { throw new IllegalStateException("Failed to transform " + typeDescription + " using " + plugin, throwable); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, List<Throwable> throwables) { throw new UnsupportedOperationException("onError"); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Map<TypeDescription, List<Throwable>> throwables) { throw new UnsupportedOperationException("onError"); } },
An error handler that fails the build after applying all plugins if at least one plugin failed.
/** * An error handler that fails the build after applying all plugins if at least one plugin failed. */
FAIL_AFTER_TYPE {
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, List<Throwable> throwables) { throw new IllegalStateException("Failed to transform " + typeDescription + ": " + throwables); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Map<TypeDescription, List<Throwable>> throwables) { throw new UnsupportedOperationException("onError"); } },
An error handler that fails the build after transforming all types if at least one plugin failed.
/** * An error handler that fails the build after transforming all types if at least one plugin failed. */
FAIL_LAST {
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, List<Throwable> throwables) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Map<TypeDescription, List<Throwable>> throwables) { throw new IllegalStateException("Failed to transform at least one type: " + throwables); } };
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Plugin plugin, Throwable throwable) { throw new IllegalStateException("Failed to close plugin " + plugin, throwable); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onLiveInitializer(TypeDescription typeDescription, TypeDescription definingType) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onUnresolved(String typeName) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onManifest(Manifest manifest) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onResource(String name) { /* do nothing */ } }
An error handler that enforces certain properties of the transformation.
/** * An error handler that enforces certain properties of the transformation. */
enum Enforcing implements ErrorHandler {
Enforces that all types could be resolved.
/** * Enforces that all types could be resolved. */
ALL_TYPES_RESOLVED { @Override public void onUnresolved(String typeName) { throw new IllegalStateException("Failed to resolve type description for " + typeName); } },
Enforces that no type has a live initializer.
/** * Enforces that no type has a live initializer. */
NO_LIVE_INITIALIZERS { @Override public void onLiveInitializer(TypeDescription typeDescription, TypeDescription initializedType) { throw new IllegalStateException("Failed to instrument " + typeDescription + " due to live initializer for " + initializedType); } },
Enforces that a source only produces class files.
/** * Enforces that a source only produces class files. */
CLASS_FILES_ONLY { @Override public void onResource(String name) { throw new IllegalStateException("Discovered a resource when only class files were allowed: " + name); } },
Enforces that a manifest is written to a target.
/** * Enforces that a manifest is written to a target. */
MANIFEST_REQUIRED { @Override public void onManifest(Manifest manifest) { if (manifest == null) { throw new IllegalStateException("Required a manifest but no manifest was found"); } } };
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, List<Throwable> throwables) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Map<TypeDescription, List<Throwable>> throwables) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Plugin plugin, Throwable throwable) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onLiveInitializer(TypeDescription typeDescription, TypeDescription definingType) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onUnresolved(String typeName) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onManifest(Manifest manifest) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onResource(String name) { /* do nothing */ } }
A compound error handler.
/** * A compound error handler. */
class Compound implements ErrorHandler {
The error handlers that are represented by this instance.
/** * The error handlers that are represented by this instance. */
private final List<ErrorHandler> errorHandlers;
Creates a new compound error handler.
Params:
  • errorHandler – The error handlers that are represented by this instance.
/** * Creates a new compound error handler. * * @param errorHandler The error handlers that are represented by this instance. */
public Compound(ErrorHandler... errorHandler) { this(Arrays.asList(errorHandler)); }
Creates a new compound error handler.
Params:
  • errorHandlers – The error handlers that are represented by this instance.
/** * Creates a new compound error handler. * * @param errorHandlers The error handlers that are represented by this instance. */
public Compound(List<? extends ErrorHandler> errorHandlers) { this.errorHandlers = new ArrayList<ErrorHandler>(); for (ErrorHandler errorHandler : errorHandlers) { if (errorHandler instanceof Compound) { this.errorHandlers.addAll(((Compound) errorHandler).errorHandlers); } else if (!(errorHandler instanceof Listener.NoOp)) { this.errorHandlers.add(errorHandler); } } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { for (ErrorHandler errorHandler : errorHandlers) { errorHandler.onError(typeDescription, plugin, throwable); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, List<Throwable> throwables) { for (ErrorHandler errorHandler : errorHandlers) { errorHandler.onError(typeDescription, throwables); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Map<TypeDescription, List<Throwable>> throwables) { for (ErrorHandler errorHandler : errorHandlers) { errorHandler.onError(throwables); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Plugin plugin, Throwable throwable) { for (ErrorHandler errorHandler : errorHandlers) { errorHandler.onError(plugin, throwable); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onLiveInitializer(TypeDescription typeDescription, TypeDescription definingType) { for (ErrorHandler errorHandler : errorHandlers) { errorHandler.onLiveInitializer(typeDescription, definingType); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onUnresolved(String typeName) { for (ErrorHandler errorHandler : errorHandlers) { errorHandler.onUnresolved(typeName); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onManifest(Manifest manifest) { for (ErrorHandler errorHandler : errorHandlers) { errorHandler.onManifest(manifest); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onResource(String name) { for (ErrorHandler errorHandler : errorHandlers) { errorHandler.onResource(name); } } } }
A listener that is invoked upon any event during a plugin engine application.
/** * A listener that is invoked upon any event during a plugin engine application. */
interface Listener extends ErrorHandler {
Invoked upon discovering a type but prior to its resolution.
Params:
  • typeName – The name of the discovered type.
/** * Invoked upon discovering a type but prior to its resolution. * * @param typeName The name of the discovered type. */
void onDiscovery(String typeName);
Invoked after a type was transformed using a specific plugin.
Params:
  • typeDescription – The type being transformed.
  • plugin – The plugin that was applied.
/** * Invoked after a type was transformed using a specific plugin. * * @param typeDescription The type being transformed. * @param plugin The plugin that was applied. */
void onTransformation(TypeDescription typeDescription, Plugin plugin);
Invoked after a type was transformed using at least one plugin.
Params:
  • typeDescription – The type being transformed.
  • plugins – A list of plugins that were applied.
/** * Invoked after a type was transformed using at least one plugin. * * @param typeDescription The type being transformed. * @param plugins A list of plugins that were applied. */
void onTransformation(TypeDescription typeDescription, List<Plugin> plugins);
Invoked if a type description is ignored by a given plugin. This callback is not invoked, if the ignore type matcher excluded a type from transformation.
Params:
  • typeDescription – The type being transformed.
  • plugin – The plugin that ignored the given type.
/** * Invoked if a type description is ignored by a given plugin. This callback is not invoked, * if the ignore type matcher excluded a type from transformation. * * @param typeDescription The type being transformed. * @param plugin The plugin that ignored the given type. */
void onIgnored(TypeDescription typeDescription, Plugin plugin);
Invoked if one or more plugins did not transform a type. This callback is also invoked if an ignore matcher excluded a type from transformation.
Params:
  • typeDescription – The type being transformed.
  • plugins – the plugins that ignored the type.
/** * Invoked if one or more plugins did not transform a type. This callback is also invoked if an * ignore matcher excluded a type from transformation. * * @param typeDescription The type being transformed. * @param plugins the plugins that ignored the type. */
void onIgnored(TypeDescription typeDescription, List<Plugin> plugins);
Invoked upon completing handling a type that was either transformed or ignored.
Params:
  • typeDescription – The type that was transformed.
/** * Invoked upon completing handling a type that was either transformed or ignored. * * @param typeDescription The type that was transformed. */
void onComplete(TypeDescription typeDescription);
A non-operational listener.
/** * A non-operational listener. */
enum NoOp implements Listener {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public void onDiscovery(String typeName) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onTransformation(TypeDescription typeDescription, Plugin plugin) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onTransformation(TypeDescription typeDescription, List<Plugin> plugins) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onIgnored(TypeDescription typeDescription, Plugin plugin) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onIgnored(TypeDescription typeDescription, List<Plugin> plugins) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, List<Throwable> throwables) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Map<TypeDescription, List<Throwable>> throwables) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Plugin plugin, Throwable throwable) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onLiveInitializer(TypeDescription typeDescription, TypeDescription definingType) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onComplete(TypeDescription typeDescription) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onUnresolved(String typeName) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onManifest(Manifest manifest) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onResource(String name) { /* do nothing */ } }
An adapter that implements all methods non-operational.
/** * An adapter that implements all methods non-operational. */
abstract class Adapter implements Listener {
{@inheritDoc}
/** * {@inheritDoc} */
public void onDiscovery(String typeName) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onTransformation(TypeDescription typeDescription, Plugin plugin) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onTransformation(TypeDescription typeDescription, List<Plugin> plugins) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onIgnored(TypeDescription typeDescription, Plugin plugin) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onIgnored(TypeDescription typeDescription, List<Plugin> plugins) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, List<Throwable> throwables) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Map<TypeDescription, List<Throwable>> throwables) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Plugin plugin, Throwable throwable) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onLiveInitializer(TypeDescription typeDescription, TypeDescription definingType) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onComplete(TypeDescription typeDescription) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onUnresolved(String typeName) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onManifest(Manifest manifest) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void onResource(String name) { /* do nothing */ } }
A listener that forwards significant events of a plugin engine application to a PrintStream.
/** * A listener that forwards significant events of a plugin engine application to a {@link PrintStream}. */
@HashCodeAndEqualsPlugin.Enhance class StreamWriting extends Adapter {
The prefix that is appended to all written messages.
/** * The prefix that is appended to all written messages. */
protected static final String PREFIX = "[Byte Buddy]";
The print stream to delegate to.
/** * The print stream to delegate to. */
private final PrintStream printStream;
Creates a new stream writing listener.
Params:
  • printStream – The print stream to delegate to.
/** * Creates a new stream writing listener. * * @param printStream The print stream to delegate to. */
public StreamWriting(PrintStream printStream) { this.printStream = printStream; }
Creates a stream writing listener that prints all events on System.out.
Returns:A listener that writes events to the system output stream.
/** * Creates a stream writing listener that prints all events on {@link System#out}. * * @return A listener that writes events to the system output stream. */
public static StreamWriting toSystemOut() { return new StreamWriting(System.out); }
Creates a stream writing listener that prints all events on System.err.
Returns:A listener that writes events to the system error stream.
/** * Creates a stream writing listener that prints all events on {@link System#err}. * * @return A listener that writes events to the system error stream. */
public static StreamWriting toSystemError() { return new StreamWriting(System.err); }
Returns a new listener that only prints transformation and error events.
Returns:A new listener that only prints transformation and error events.
/** * Returns a new listener that only prints transformation and error events. * * @return A new listener that only prints transformation and error events. */
public Listener withTransformationsOnly() { return new WithTransformationsOnly(this); }
Returns a new listener that only prints error events.
Returns:A new listener that only prints error events.
/** * Returns a new listener that only prints error events. * * @return A new listener that only prints error events. */
public Listener withErrorsOnly() { return new WithErrorsOnly(this); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onDiscovery(String typeName) { printStream.printf(PREFIX + " DISCOVERY %s", typeName); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onTransformation(TypeDescription typeDescription, Plugin plugin) { printStream.printf(PREFIX + " TRANSFORM %s for %s", typeDescription, plugin); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onIgnored(TypeDescription typeDescription, Plugin plugin) { printStream.printf(PREFIX + " IGNORE %s for %s", typeDescription, plugin); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { synchronized (printStream) { printStream.printf(PREFIX + " ERROR %s for %s", typeDescription, plugin); throwable.printStackTrace(printStream); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Plugin plugin, Throwable throwable) { synchronized (printStream) { printStream.printf(PREFIX + " ERROR %s", plugin); throwable.printStackTrace(printStream); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onUnresolved(String typeName) { printStream.printf(PREFIX + " UNRESOLVED %s", typeName); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onLiveInitializer(TypeDescription typeDescription, TypeDescription definingType) { printStream.printf(PREFIX + " LIVE %s on %s", typeDescription, definingType); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onComplete(TypeDescription typeDescription) { printStream.printf(PREFIX + " COMPLETE %s", typeDescription); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onManifest(Manifest manifest) { printStream.printf(PREFIX + " MANIFEST %b", manifest != null); }
{@inheritDoc}
/** * {@inheritDoc} */
public void onResource(String name) { printStream.printf(PREFIX + " RESOURCE %s", name); } }
A decorator for another listener to only print transformation and error events.
/** * A decorator for another listener to only print transformation and error events. */
@HashCodeAndEqualsPlugin.Enhance class WithTransformationsOnly extends Adapter {
The delegate to forward events to.
/** * The delegate to forward events to. */
private final Listener delegate;
Creates a new listener decorator that filter any event that is not related to transformation or errors.
Params:
  • delegate – The delegate to forward events to.
/** * Creates a new listener decorator that filter any event that is not related to transformation or errors. * * @param delegate The delegate to forward events to. */
public WithTransformationsOnly(Listener delegate) { this.delegate = delegate; } @Override public void onTransformation(TypeDescription typeDescription, Plugin plugin) { delegate.onTransformation(typeDescription, plugin); } @Override public void onTransformation(TypeDescription typeDescription, List<Plugin> plugins) { delegate.onTransformation(typeDescription, plugins); } @Override public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { delegate.onError(typeDescription, plugin, throwable); } @Override public void onError(TypeDescription typeDescription, List<Throwable> throwables) { delegate.onError(typeDescription, throwables); } @Override public void onError(Map<TypeDescription, List<Throwable>> throwables) { delegate.onError(throwables); } @Override public void onError(Plugin plugin, Throwable throwable) { delegate.onError(plugin, throwable); } }
A decorator for another listener to only print error events.
/** * A decorator for another listener to only print error events. */
@HashCodeAndEqualsPlugin.Enhance class WithErrorsOnly extends Adapter {
The delegate to forward events to.
/** * The delegate to forward events to. */
private final Listener delegate;
Creates a new listener decorator that filter any event that is not related to errors.
Params:
  • delegate – The delegate to forward events to.
/** * Creates a new listener decorator that filter any event that is not related to errors. * * @param delegate The delegate to forward events to. */
public WithErrorsOnly(Listener delegate) { this.delegate = delegate; } @Override public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { delegate.onError(typeDescription, plugin, throwable); } @Override public void onError(TypeDescription typeDescription, List<Throwable> throwables) { delegate.onError(typeDescription, throwables); } @Override public void onError(Map<TypeDescription, List<Throwable>> throwables) { delegate.onError(throwables); } @Override public void onError(Plugin plugin, Throwable throwable) { delegate.onError(plugin, throwable); } }
A listener decorator that forwards events to an error handler if they are applicable.
/** * A listener decorator that forwards events to an error handler if they are applicable. */
@HashCodeAndEqualsPlugin.Enhance class ForErrorHandler extends Adapter {
The error handler to delegate to.
/** * The error handler to delegate to. */
private final ErrorHandler errorHandler;
Creates a new listener representation for an error handler.
Params:
  • errorHandler – The error handler to delegate to.
/** * Creates a new listener representation for an error handler. * * @param errorHandler The error handler to delegate to. */
public ForErrorHandler(ErrorHandler errorHandler) { this.errorHandler = errorHandler; } @Override public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { errorHandler.onError(typeDescription, plugin, throwable); } @Override public void onError(TypeDescription typeDescription, List<Throwable> throwables) { errorHandler.onError(typeDescription, throwables); } @Override public void onError(Map<TypeDescription, List<Throwable>> throwables) { errorHandler.onError(throwables); } @Override public void onError(Plugin plugin, Throwable throwable) { errorHandler.onError(plugin, throwable); } @Override public void onLiveInitializer(TypeDescription typeDescription, TypeDescription definingType) { errorHandler.onLiveInitializer(typeDescription, definingType); } @Override public void onUnresolved(String typeName) { errorHandler.onUnresolved(typeName); } @Override public void onManifest(Manifest manifest) { errorHandler.onManifest(manifest); } @Override public void onResource(String name) { errorHandler.onResource(name); } }
A compound listener.
/** * A compound listener. */
@HashCodeAndEqualsPlugin.Enhance class Compound implements Listener {
A list of listeners that are represented by this compound instance.
/** * A list of listeners that are represented by this compound instance. */
private final List<Listener> listeners;
Creates a new compound listener.
Params:
  • listener – A list of listeners that are represented by this compound instance.
/** * Creates a new compound listener. * * @param listener A list of listeners that are represented by this compound instance. */
public Compound(Listener... listener) { this(Arrays.asList(listener)); }
Creates a new compound listener.
Params:
  • listeners – A list of listeners that are represented by this compound instance.
/** * Creates a new compound listener. * * @param listeners A list of listeners that are represented by this compound instance. */
public Compound(List<? extends Listener> listeners) { this.listeners = new ArrayList<Listener>(); for (Listener listener : listeners) { if (listener instanceof Listener.Compound) { this.listeners.addAll(((Listener.Compound) listener).listeners); } else if (!(listener instanceof NoOp)) { this.listeners.add(listener); } } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onDiscovery(String typeName) { for (Listener listener : listeners) { listener.onDiscovery(typeName); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onTransformation(TypeDescription typeDescription, Plugin plugin) { for (Listener listener : listeners) { listener.onTransformation(typeDescription, plugin); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onTransformation(TypeDescription typeDescription, List<Plugin> plugins) { for (Listener listener : listeners) { listener.onTransformation(typeDescription, plugins); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onIgnored(TypeDescription typeDescription, Plugin plugin) { for (Listener listener : listeners) { listener.onIgnored(typeDescription, plugin); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onIgnored(TypeDescription typeDescription, List<Plugin> plugins) { for (Listener listener : listeners) { listener.onIgnored(typeDescription, plugins); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, Plugin plugin, Throwable throwable) { for (Listener listener : listeners) { listener.onError(typeDescription, plugin, throwable); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(TypeDescription typeDescription, List<Throwable> throwables) { for (Listener listener : listeners) { listener.onError(typeDescription, throwables); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Map<TypeDescription, List<Throwable>> throwables) { for (Listener listener : listeners) { listener.onError(throwables); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onError(Plugin plugin, Throwable throwable) { for (Listener listener : listeners) { listener.onError(plugin, throwable); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onLiveInitializer(TypeDescription typeDescription, TypeDescription definingType) { for (Listener listener : listeners) { listener.onLiveInitializer(typeDescription, definingType); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onComplete(TypeDescription typeDescription) { for (Listener listener : listeners) { listener.onComplete(typeDescription); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onUnresolved(String typeName) { for (Listener listener : listeners) { listener.onUnresolved(typeName); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onManifest(Manifest manifest) { for (Listener listener : listeners) { listener.onManifest(manifest); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void onResource(String name) { for (Listener listener : listeners) { listener.onResource(name); } } } }
A source for a plugin engine provides binary elements to consider for transformation.
/** * A source for a plugin engine provides binary elements to consider for transformation. */
interface Source {
Initiates reading from a source.
Throws:
Returns:The origin to read from.
/** * Initiates reading from a source. * * @return The origin to read from. * @throws IOException If an I/O error occurs. */
Origin read() throws IOException;
An origin for elements.
/** * An origin for elements. */
interface Origin extends Iterable<Element>, Closeable {
Indicates that no manifest exists.
/** * Indicates that no manifest exists. */
Manifest NO_MANIFEST = null;
Returns the manifest file of the source location or null if no manifest exists.
Throws:
Returns:This source's manifest or null.
/** * Returns the manifest file of the source location or {@code null} if no manifest exists. * * @return This source's manifest or {@code null}. * @throws IOException If an I/O error occurs. */
Manifest getManifest() throws IOException;
Returns a class file locator for the represented source. If the class file locator needs to be closed, it is the responsibility of this origin to close the locator or its underlying resources.
Returns:A class file locator for locating class files of this instance..
/** * Returns a class file locator for the represented source. If the class file locator needs to be closed, it is the responsibility * of this origin to close the locator or its underlying resources. * * @return A class file locator for locating class files of this instance.. */
ClassFileLocator getClassFileLocator();
An origin implementation for a jar file.
/** * An origin implementation for a jar file. */
class ForJarFile implements Origin {
The represented file.
/** * The represented file. */
private final JarFile file;
Creates a new origin for a jar file.
Params:
  • file – The represented file.
/** * Creates a new origin for a jar file. * * @param file The represented file. */
public ForJarFile(JarFile file) { this.file = file; }
{@inheritDoc}
/** * {@inheritDoc} */
public Manifest getManifest() throws IOException { return file.getManifest(); }
{@inheritDoc}
/** * {@inheritDoc} */
public ClassFileLocator getClassFileLocator() { return new ClassFileLocator.ForJarFile(file); }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() throws IOException { file.close(); }
{@inheritDoc}
/** * {@inheritDoc} */
public Iterator<Element> iterator() { return new JarFileIterator(file.entries()); }
An iterator for jar file entries.
/** * An iterator for jar file entries. */
protected class JarFileIterator implements Iterator<Element> {
The represented enumeration.
/** * The represented enumeration. */
private final Enumeration<JarEntry> enumeration;
Creates a new jar file iterator.
Params:
  • enumeration – The represented enumeration.
/** * Creates a new jar file iterator. * * @param enumeration The represented enumeration. */
protected JarFileIterator(Enumeration<JarEntry> enumeration) { this.enumeration = enumeration; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean hasNext() { return enumeration.hasMoreElements(); }
{@inheritDoc}
/** * {@inheritDoc} */
public Element next() { return new Element.ForJarEntry(file, enumeration.nextElement()); }
{@inheritDoc}
/** * {@inheritDoc} */
public void remove() { throw new UnsupportedOperationException("remove"); } } } }
Represents a binary element found in a source location.
/** * Represents a binary element found in a source location. */
interface Element {
Returns the element's relative path and name.
Returns:The element's path and name.
/** * Returns the element's relative path and name. * * @return The element's path and name. */
String getName();
Returns an input stream to read this element's binary information.
Throws:
Returns:An input stream that represents this element's binary information.
/** * Returns an input stream to read this element's binary information. * * @return An input stream that represents this element's binary information. * @throws IOException If an I/O error occurs. */
InputStream getInputStream() throws IOException;
Resolves this element to a more specialized form if possible. Doing so allows for performance optimizations if more specialized formats are available.
Params:
  • type – The requested spezialized type.
Type parameters:
  • <T> – The requested spezialized type.
Returns:The resolved element or null if a transformation is impossible.
/** * Resolves this element to a more specialized form if possible. Doing so allows for performance * optimizations if more specialized formats are available. * * @param type The requested spezialized type. * @param <T> The requested spezialized type. * @return The resolved element or {@code null} if a transformation is impossible. */
<T> T resolveAs(Class<T> type);
An element representation for a byte array.
/** * An element representation for a byte array. */
@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Not mutating the byte array is part of the class contract.") @HashCodeAndEqualsPlugin.Enhance class ForByteArray implements Element {
The element's name.
/** * The element's name. */
private final String name;
The element's binary representation.
/** * The element's binary representation. */
private final byte[] binaryRepresentation;
Creates an element that is represented by a byte array.
Params:
  • name – The element's name.
  • binaryRepresentation – The element's binary representation.
/** * Creates an element that is represented by a byte array. * * @param name The element's name. * @param binaryRepresentation The element's binary representation. */
public ForByteArray(String name, byte[] binaryRepresentation) { this.name = name; this.binaryRepresentation = binaryRepresentation; }
{@inheritDoc}
/** * {@inheritDoc} */
public String getName() { return name; }
{@inheritDoc}
/** * {@inheritDoc} */
public InputStream getInputStream() { return new ByteArrayInputStream(binaryRepresentation); }
{@inheritDoc}
/** * {@inheritDoc} */
public <T> T resolveAs(Class<T> type) { return null; } }
An element representation for a file.
/** * An element representation for a file. */
@HashCodeAndEqualsPlugin.Enhance class ForFile implements Element {
The root folder of the represented source.
/** * The root folder of the represented source. */
private final File root;
The file location of the represented file that is located within the root directory.
/** * The file location of the represented file that is located within the root directory. */
private final File file;
Creates an element representation for a file.
Params:
  • root – The root folder of the represented source.
  • file – The file location of the represented file that is located within the root directory.
/** * Creates an element representation for a file. * * @param root The root folder of the represented source. * @param file The file location of the represented file that is located within the root directory. */
public ForFile(File root, File file) { this.root = root; this.file = file; }
{@inheritDoc}
/** * {@inheritDoc} */
public String getName() { return root.getAbsoluteFile().toURI().relativize(file.getAbsoluteFile().toURI()).getPath(); }
{@inheritDoc}
/** * {@inheritDoc} */
public InputStream getInputStream() throws IOException { return new FileInputStream(file); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressWarnings("unchecked") public <T> T resolveAs(Class<T> type) { return File.class.isAssignableFrom(type) ? (T) file : null; } }
Represents a jar file entry as an element.
/** * Represents a jar file entry as an element. */
@HashCodeAndEqualsPlugin.Enhance class ForJarEntry implements Element {
The source's underlying jar file.
/** * The source's underlying jar file. */
private final JarFile file;
The entry that is represented by this element.
/** * The entry that is represented by this element. */
private final JarEntry entry;
Creates a new element representation for a jar file entry.
Params:
  • file – The source's underlying jar file.
  • entry – The entry that is represented by this element.
/** * Creates a new element representation for a jar file entry. * * @param file The source's underlying jar file. * @param entry The entry that is represented by this element. */
public ForJarEntry(JarFile file, JarEntry entry) { this.file = file; this.entry = entry; }
{@inheritDoc}
/** * {@inheritDoc} */
public String getName() { return entry.getName(); }
{@inheritDoc}
/** * {@inheritDoc} */
public InputStream getInputStream() throws IOException { return file.getInputStream(entry); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressWarnings("unchecked") public <T> T resolveAs(Class<T> type) { return JarEntry.class.isAssignableFrom(type) ? (T) entry : null; } } }
An empty source that does not contain any elements or a manifest.
/** * An empty source that does not contain any elements or a manifest. */
enum Empty implements Source, Origin {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public Origin read() { return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public ClassFileLocator getClassFileLocator() { return ClassFileLocator.NoOp.INSTANCE; }
{@inheritDoc}
/** * {@inheritDoc} */
public Manifest getManifest() { return NO_MANIFEST; }
{@inheritDoc}
/** * {@inheritDoc} */
public Iterator<Element> iterator() { return Collections.<Element>emptySet().iterator(); }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() { /* do nothing */ } }
A source that represents a collection of in-memory resources that are represented as byte arrays.
/** * A source that represents a collection of in-memory resources that are represented as byte arrays. */
@HashCodeAndEqualsPlugin.Enhance class InMemory implements Source, Origin {
A mapping of resource names to their binary representation.
/** * A mapping of resource names to their binary representation. */
private final Map<String, byte[]> storage;
Creates a new in-memory source.
Params:
  • storage – A mapping of resource names to their binary representation.
/** * Creates a new in-memory source. * * @param storage A mapping of resource names to their binary representation. */
public InMemory(Map<String, byte[]> storage) { this.storage = storage; }
Represents a collection of types as a in-memory source.
Params:
  • type – The types to represent.
Returns:A source representing the supplied types.
/** * Represents a collection of types as a in-memory source. * * @param type The types to represent. * @return A source representing the supplied types. */
public static Source ofTypes(Class<?>... type) { return ofTypes(Arrays.asList(type)); }
Represents a collection of types as a in-memory source.
Params:
  • types – The types to represent.
Returns:A source representing the supplied types.
/** * Represents a collection of types as a in-memory source. * * @param types The types to represent. * @return A source representing the supplied types. */
public static Source ofTypes(Collection<? extends Class<?>> types) { Map<TypeDescription, byte[]> binaryRepresentations = new HashMap<TypeDescription, byte[]>(); for (Class<?> type : types) { binaryRepresentations.put(TypeDescription.ForLoadedType.of(type), ClassFileLocator.ForClassLoader.read(type)); } return ofTypes(binaryRepresentations); }
Represents a map of type names to their binary representation as an in-memory source.
Params:
  • binaryRepresentations – A mapping of type names to their binary representation.
Returns:A source representing the supplied types.
/** * Represents a map of type names to their binary representation as an in-memory source. * * @param binaryRepresentations A mapping of type names to their binary representation. * @return A source representing the supplied types. */
public static Source ofTypes(Map<TypeDescription, byte[]> binaryRepresentations) { Map<String, byte[]> storage = new HashMap<String, byte[]>(); for (Map.Entry<TypeDescription, byte[]> entry : binaryRepresentations.entrySet()) { storage.put(entry.getKey().getInternalName() + CLASS_FILE_EXTENSION, entry.getValue()); } return new InMemory(storage); }
{@inheritDoc}
/** * {@inheritDoc} */
public Origin read() { return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public ClassFileLocator getClassFileLocator() { return ClassFileLocator.Simple.ofResources(storage); }
{@inheritDoc}
/** * {@inheritDoc} */
public Manifest getManifest() throws IOException { byte[] binaryRepresentation = storage.get(JarFile.MANIFEST_NAME); if (binaryRepresentation == null) { return NO_MANIFEST; } else { return new Manifest(new ByteArrayInputStream(binaryRepresentation)); } }
{@inheritDoc}
/** * {@inheritDoc} */
public Iterator<Element> iterator() { return new MapEntryIterator(storage.entrySet().iterator()); }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() { /* do nothing */ }
An iterator that represents map entries as sources.
/** * An iterator that represents map entries as sources. */
protected static class MapEntryIterator implements Iterator<Element> {
The represented iterator.
/** * The represented iterator. */
private final Iterator<Map.Entry<String, byte[]>> iterator;
Creates a new map entry iterator.
Params:
  • iterator – The represented iterator.
/** * Creates a new map entry iterator. * * @param iterator The represented iterator. */
protected MapEntryIterator(Iterator<Map.Entry<String, byte[]>> iterator) { this.iterator = iterator; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean hasNext() { return iterator.hasNext(); }
{@inheritDoc}
/** * {@inheritDoc} */
public Element next() { Map.Entry<String, byte[]> entry = iterator.next(); return new Element.ForByteArray(entry.getKey(), entry.getValue()); }
{@inheritDoc}
/** * {@inheritDoc} */
public void remove() { throw new UnsupportedOperationException("remove"); } } }
Represents the contents of a folder as class files.
/** * Represents the contents of a folder as class files. */
@HashCodeAndEqualsPlugin.Enhance class ForFolder implements Source, Origin {
The folder to represent.
/** * The folder to represent. */
private final File folder;
Creates a new source representation for a given folder.
Params:
  • folder – The folder to represent.
/** * Creates a new source representation for a given folder. * * @param folder The folder to represent. */
public ForFolder(File folder) { this.folder = folder; }
Initializes a reading from this source.
Returns:A source that represents the resource of this origin.
/** * Initializes a reading from this source. * * @return A source that represents the resource of this origin. */
public Origin read() { return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public ClassFileLocator getClassFileLocator() { return new ClassFileLocator.ForFolder(folder); }
{@inheritDoc}
/** * {@inheritDoc} */
public Manifest getManifest() throws IOException { File file = new File(folder, JarFile.MANIFEST_NAME); if (file.exists()) { InputStream inputStream = new FileInputStream(file); try { return new Manifest(inputStream); } finally { inputStream.close(); } } else { return NO_MANIFEST; } }
{@inheritDoc}
/** * {@inheritDoc} */
public Iterator<Element> iterator() { return new FolderIterator(folder); }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() { /* do nothing */ }
An iterator that exposes all files within a folder structure as elements.
/** * An iterator that exposes all files within a folder structure as elements. */
protected class FolderIterator implements Iterator<Element> {
A list of files and folders to process.
/** * A list of files and folders to process. */
private final LinkedList<File> files;
Creates a new iterator representation for all files within a folder.
Params:
  • folder – The root folder.
/** * Creates a new iterator representation for all files within a folder. * * @param folder The root folder. */
protected FolderIterator(File folder) { files = new LinkedList<File>(Collections.singleton(folder)); File candidate; do { candidate = files.removeFirst(); File[] file = candidate.listFiles(); if (file != null) { files.addAll(0, Arrays.asList(file)); } } while (!files.isEmpty() && (files.peek().isDirectory() || files.peek().equals(new File(folder, JarFile.MANIFEST_NAME)))); }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean hasNext() { return !files.isEmpty(); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "IT_NO_SUCH_ELEMENT", justification = "Exception is thrown by invoking removeFirst on an empty list.") public Element next() { try { return new Element.ForFile(folder, files.removeFirst()); } finally { while (!files.isEmpty() && (files.peek().isDirectory() || files.peek().equals(new File(folder, JarFile.MANIFEST_NAME)))) { File folder = files.removeFirst(); File[] file = folder.listFiles(); if (file != null) { files.addAll(0, Arrays.asList(file)); } } } }
{@inheritDoc}
/** * {@inheritDoc} */
public void remove() { throw new UnsupportedOperationException("remove"); } } }
Represents a jar file as a source.
/** * Represents a jar file as a source. */
@HashCodeAndEqualsPlugin.Enhance class ForJarFile implements Source {
The jar file being represented by this source.
/** * The jar file being represented by this source. */
private final File file;
Creates a new source for a jar file.
Params:
  • file – The jar file being represented by this source.
/** * Creates a new source for a jar file. * * @param file The jar file being represented by this source. */
public ForJarFile(File file) { this.file = file; }
{@inheritDoc}
/** * {@inheritDoc} */
public Origin read() throws IOException { return new Origin.ForJarFile(new JarFile(file)); } } }
A target for a plugin engine represents a sink container for all elements that are supplied by a Source.
/** * A target for a plugin engine represents a sink container for all elements that are supplied by a {@link Source}. */
interface Target {
Initializes this target prior to writing.
Params:
  • manifest – The manifest for the target or null if no manifest was found.
Throws:
Returns:The sink to write to.
/** * Initializes this target prior to writing. * * @param manifest The manifest for the target or {@code null} if no manifest was found. * @return The sink to write to. * @throws IOException If an I/O error occurs. */
Sink write(Manifest manifest) throws IOException;
A sink represents an active writing process.
/** * A sink represents an active writing process. */
interface Sink extends Closeable {
Stores the supplied binary representation of types in this sink.
Params:
  • binaryRepresentations – The binary representations to store.
Throws:
/** * Stores the supplied binary representation of types in this sink. * * @param binaryRepresentations The binary representations to store. * @throws IOException If an I/O error occurs. */
void store(Map<TypeDescription, byte[]> binaryRepresentations) throws IOException;
Retains the supplied element in its original form.
Params:
  • element – The element to retain.
Throws:
/** * Retains the supplied element in its original form. * * @param element The element to retain. * @throws IOException If an I/O error occurs. */
void retain(Source.Element element) throws IOException;
Implements a sink for a jar file.
/** * Implements a sink for a jar file. */
class ForJarOutputStream implements Sink {
The output stream to write to.
/** * The output stream to write to. */
private final JarOutputStream outputStream;
Creates a new sink for a jar file.
Params:
  • outputStream – The output stream to write to.
/** * Creates a new sink for a jar file. * * @param outputStream The output stream to write to. */
public ForJarOutputStream(JarOutputStream outputStream) { this.outputStream = outputStream; }
{@inheritDoc}
/** * {@inheritDoc} */
public void store(Map<TypeDescription, byte[]> binaryRepresentations) throws IOException { for (Map.Entry<TypeDescription, byte[]> entry : binaryRepresentations.entrySet()) { outputStream.putNextEntry(new JarEntry(entry.getKey().getInternalName() + CLASS_FILE_EXTENSION)); outputStream.write(entry.getValue()); outputStream.closeEntry(); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void retain(Source.Element element) throws IOException { JarEntry entry = element.resolveAs(JarEntry.class); outputStream.putNextEntry(entry == null ? new JarEntry(element.getName()) : entry); InputStream inputStream = element.getInputStream(); try { byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, length); } } finally { inputStream.close(); } outputStream.closeEntry(); }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() throws IOException { outputStream.close(); } } }
A sink that discards any entry.
/** * A sink that discards any entry. */
enum Discarding implements Target, Sink {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public Sink write(Manifest manifest) { return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public void store(Map<TypeDescription, byte[]> binaryRepresentations) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void retain(Source.Element element) { /* do nothing */ }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() { /* do nothing */ } }
A sink that stores all elements in a memory map.
/** * A sink that stores all elements in a memory map. */
@HashCodeAndEqualsPlugin.Enhance class InMemory implements Target, Sink {
The map for storing all elements being received.
/** * The map for storing all elements being received. */
private final Map<String, byte[]> storage;
Creates a new in-memory storage.
/** * Creates a new in-memory storage. */
public InMemory() { this(new HashMap<String, byte[]>()); }
Creates a new in-memory storage.
Params:
  • storage – The map for storing all elements being received.
/** * Creates a new in-memory storage. * * @param storage The map for storing all elements being received. */
public InMemory(Map<String, byte[]> storage) { this.storage = storage; }
{@inheritDoc}
/** * {@inheritDoc} */
public Sink write(Manifest manifest) throws IOException { if (manifest != null) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { manifest.write(outputStream); } finally { outputStream.close(); } storage.put(JarFile.MANIFEST_NAME, outputStream.toByteArray()); } return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public void store(Map<TypeDescription, byte[]> binaryRepresentations) { for (Map.Entry<TypeDescription, byte[]> entry : binaryRepresentations.entrySet()) { storage.put(entry.getKey().getInternalName() + CLASS_FILE_EXTENSION, entry.getValue()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void retain(Source.Element element) throws IOException { String name = element.getName(); if (!name.endsWith("/")) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { InputStream inputStream = element.getInputStream(); try { byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, length); } } finally { inputStream.close(); } } finally { outputStream.close(); } storage.put(element.getName(), outputStream.toByteArray()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() { /* do nothing */ }
Returns the in-memory storage.
Returns:The in-memory storage.
/** * Returns the in-memory storage. * * @return The in-memory storage. */
public Map<String, byte[]> getStorage() { return storage; }
Returns the in-memory storage as a type-map where all non-class files are discarded.
Returns:The in-memory storage as a type map.
/** * Returns the in-memory storage as a type-map where all non-class files are discarded. * * @return The in-memory storage as a type map. */
public Map<String, byte[]> toTypeMap() { Map<String, byte[]> binaryRepresentations = new HashMap<String, byte[]>(); for (Map.Entry<String, byte[]> entry : storage.entrySet()) { if (entry.getKey().endsWith(CLASS_FILE_EXTENSION)) { binaryRepresentations.put(entry.getKey() .substring(0, entry.getKey().length() - CLASS_FILE_EXTENSION.length()) .replace('/', '.'), entry.getValue()); } } return binaryRepresentations; } }
Represents a folder as the target for a plugin engine's application.
/** * Represents a folder as the target for a plugin engine's application. */
@HashCodeAndEqualsPlugin.Enhance class ForFolder implements Target, Sink {
A dispatcher for using NIO2 if the current VM supports it.
/** * A dispatcher for using NIO2 if the current VM supports it. */
protected static final Dispatcher DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE);
The folder that is represented by this instance.
/** * The folder that is represented by this instance. */
private final File folder;
Creates a new target for a folder.
Params:
  • folder – The folder that is represented by this instance.
/** * Creates a new target for a folder. * * @param folder The folder that is represented by this instance. */
public ForFolder(File folder) { this.folder = folder; }
{@inheritDoc}
/** * {@inheritDoc} */
public Sink write(Manifest manifest) throws IOException { if (manifest != null) { File target = new File(folder, JarFile.MANIFEST_NAME); if (!target.getParentFile().isDirectory() && !target.getParentFile().mkdirs()) { throw new IOException("Could not create directory: " + target.getParent()); } OutputStream outputStream = new FileOutputStream(target); try { manifest.write(outputStream); } finally { outputStream.close(); } } return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public void store(Map<TypeDescription, byte[]> binaryRepresentations) throws IOException { for (Map.Entry<TypeDescription, byte[]> entry : binaryRepresentations.entrySet()) { File target = new File(folder, entry.getKey().getInternalName() + CLASS_FILE_EXTENSION); if (!target.getParentFile().isDirectory() && !target.getParentFile().mkdirs()) { throw new IOException("Could not create directory: " + target.getParent()); } OutputStream outputStream = new FileOutputStream(target); try { outputStream.write(entry.getValue()); } finally { outputStream.close(); } } }
{@inheritDoc}
/** * {@inheritDoc} */
public void retain(Source.Element element) throws IOException { String name = element.getName(); if (!name.endsWith("/")) { File target = new File(folder, name), resolved = element.resolveAs(File.class); if (!target.getCanonicalPath().startsWith(folder.getCanonicalPath())) { throw new IllegalArgumentException(target + " is not a subdirectory of " + folder); } else if (!target.getParentFile().isDirectory() && !target.getParentFile().mkdirs()) { throw new IOException("Could not create directory: " + target.getParent()); } else if (DISPATCHER.isAlive() && resolved != null && !resolved.equals(target)) { DISPATCHER.copy(resolved, target); } else if (!target.equals(resolved)) { InputStream inputStream = element.getInputStream(); try { OutputStream outputStream = new FileOutputStream(target); try { byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, length); } } finally { outputStream.close(); } } finally { inputStream.close(); } } } }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() { /* do nothing */ }
A dispatcher that allows for file copy operations based on NIO2 if available.
/** * A dispatcher that allows for file copy operations based on NIO2 if available. */
protected interface Dispatcher {
Returns true if this dispatcher is alive.
Returns:true if this dispatcher is alive.
/** * Returns {@code true} if this dispatcher is alive. * * @return {@code true} if this dispatcher is alive. */
boolean isAlive();
Copies the source file to the target location.
Params:
  • source – The source file.
  • target – The target file.
Throws:
/** * Copies the source file to the target location. * * @param source The source file. * @param target The target file. * @throws IOException If an I/O error occurs. */
void copy(File source, File target) throws IOException;
An action for creating a dispatcher.
/** * An action for creating a dispatcher. */
enum CreationAction implements PrivilegedAction<Dispatcher> {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressWarnings("unchecked") public Dispatcher run() { try { Class<?> path = Class.forName("java.nio.file.Path"); Object[] arguments = (Object[]) Array.newInstance(Class.forName("java.nio.file.CopyOption"), 1); arguments[0] = Enum.valueOf((Class) Class.forName("java.nio.file.StandardCopyOption"), "REPLACE_EXISTING"); return new ForJava7CapableVm(File.class.getMethod("toPath"), Class.forName("java.nio.file.Files").getMethod("copy", path, path, arguments.getClass()), arguments); } catch (Throwable ignored) { return ForLegacyVm.INSTANCE; } } }
A legacy dispatcher that is not capable of NIO.
/** * A legacy dispatcher that is not capable of NIO. */
enum ForLegacyVm implements Dispatcher {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isAlive() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
public void copy(File source, File target) { throw new UnsupportedOperationException("Cannot use NIO2 copy on current VM"); } }
A dispatcher for VMs that are capable of NIO2.
/** * A dispatcher for VMs that are capable of NIO2. */
@HashCodeAndEqualsPlugin.Enhance class ForJava7CapableVm implements Dispatcher {
The java.io.File#toPath() method.
/** * The {@code java.io.File#toPath()} method. */
private final Method toPath;
The java.nio.Files#copy(Path,Path,CopyOption[]) method.
/** * The {@code java.nio.Files#copy(Path,Path,CopyOption[])} method. */
private final Method copy;
The copy options to apply.
/** * The copy options to apply. */
private final Object[] copyOptions;
Creates a new NIO2 capable dispatcher.
Params:
  • toPath – The java.io.File#toPath() method.
  • copy – The java.nio.Files#copy(Path,Path,CopyOption[]) method.
  • copyOptions – The copy options to apply.
/** * Creates a new NIO2 capable dispatcher. * * @param toPath The {@code java.io.File#toPath()} method. * @param copy The {@code java.nio.Files#copy(Path,Path,CopyOption[])} method. * @param copyOptions The copy options to apply. */
protected ForJava7CapableVm(Method toPath, Method copy, Object[] copyOptions) { this.toPath = toPath; this.copy = copy; this.copyOptions = copyOptions; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isAlive() { return true; }
{@inheritDoc}
/** * {@inheritDoc} */
public void copy(File source, File target) throws IOException { try { copy.invoke(null, toPath.invoke(source), toPath.invoke(target), copyOptions); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access NIO file copy", exception); } catch (InvocationTargetException exception) { Throwable cause = exception.getCause(); if (cause instanceof IOException) { throw (IOException) cause; } else { throw new IllegalStateException("Cannot execute NIO file copy", cause); } } } } } }
Represents a jar file as a target.
/** * Represents a jar file as a target. */
@HashCodeAndEqualsPlugin.Enhance class ForJarFile implements Target {
The jar file that is represented by this target.
/** * The jar file that is represented by this target. */
private final File file;
Creates a new target for a jar file.
Params:
  • file – The jar file that is represented by this target.
/** * Creates a new target for a jar file. * * @param file The jar file that is represented by this target. */
public ForJarFile(File file) { this.file = file; }
{@inheritDoc}
/** * {@inheritDoc} */
public Sink write(Manifest manifest) throws IOException { return manifest == null ? new Sink.ForJarOutputStream(new JarOutputStream(new FileOutputStream(file))) : new Sink.ForJarOutputStream(new JarOutputStream(new FileOutputStream(file), manifest)); } } }
A summary of the application of a Engine to a source and target.
/** * A summary of the application of a {@link Engine} to a source and target. */
class Summary {
A list of all types that were transformed.
/** * A list of all types that were transformed. */
private final List<TypeDescription> transformed;
A mapping of all types that failed during transformation to the exceptions that explain the failure.
/** * A mapping of all types that failed during transformation to the exceptions that explain the failure. */
private final Map<TypeDescription, List<Throwable>> failed;
A list of type names that could not be resolved.
/** * A list of type names that could not be resolved. */
private final List<String> unresolved;
Creates a new summary.
Params:
  • transformed – A list of all types that were transformed.
  • failed – A mapping of all types that failed during transformation to the exceptions that explain the failure.
  • unresolved – A list of type names that could not be resolved.
/** * Creates a new summary. * * @param transformed A list of all types that were transformed. * @param failed A mapping of all types that failed during transformation to the exceptions that explain the failure. * @param unresolved A list of type names that could not be resolved. */
public Summary(List<TypeDescription> transformed, Map<TypeDescription, List<Throwable>> failed, List<String> unresolved) { this.transformed = transformed; this.failed = failed; this.unresolved = unresolved; }
Returns a list of all types that were transformed.
Returns:A list of all types that were transformed.
/** * Returns a list of all types that were transformed. * * @return A list of all types that were transformed. */
public List<TypeDescription> getTransformed() { return transformed; }
Returns a mapping of all types that failed during transformation to the exceptions that explain the failure.
Returns:A mapping of all types that failed during transformation to the exceptions that explain the failure.
/** * Returns a mapping of all types that failed during transformation to the exceptions that explain the failure. * * @return A mapping of all types that failed during transformation to the exceptions that explain the failure. */
public Map<TypeDescription, List<Throwable>> getFailed() { return failed; }
Returns a list of type names that could not be resolved.
Returns:A list of type names that could not be resolved.
/** * Returns a list of type names that could not be resolved. * * @return A list of type names that could not be resolved. */
public List<String> getUnresolved() { return unresolved; } @Override public int hashCode() { int result = transformed.hashCode(); result = 31 * result + failed.hashCode(); result = 31 * result + unresolved.hashCode(); return result; } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (other == null || getClass() != other.getClass()) { return false; } Summary summary = (Summary) other; return transformed.equals(summary.transformed) && failed.equals(summary.failed) && unresolved.equals(summary.unresolved); } }
An abstract base implementation of a plugin engine.
/** * An abstract base implementation of a plugin engine. */
abstract class AbstractBase implements Engine {
{@inheritDoc}
/** * {@inheritDoc} */
public Engine withErrorHandlers(ErrorHandler... errorHandler) { return withErrorHandlers(Arrays.asList(errorHandler)); }
{@inheritDoc}
/** * {@inheritDoc} */
public Summary apply(File source, File target, Factory... factory) throws IOException { return apply(source, target, Arrays.asList(factory)); }
{@inheritDoc}
/** * {@inheritDoc} */
public Summary apply(File source, File target, List<? extends Factory> factories) throws IOException { return apply(source.isDirectory() ? new Source.ForFolder(source) : new Source.ForJarFile(source), target.isDirectory() ? new Target.ForFolder(target) : new Target.ForJarFile(target), factories); }
{@inheritDoc}
/** * {@inheritDoc} */
public Summary apply(Source source, Target target, Factory... factory) throws IOException { return apply(source, target, Arrays.asList(factory)); } }
A default implementation of a plugin engine.
/** * A default implementation of a plugin engine. */
@HashCodeAndEqualsPlugin.Enhance class Default extends AbstractBase {
The Byte Buddy instance to use.
/** * The Byte Buddy instance to use. */
private final ByteBuddy byteBuddy;
The type strategy to use.
/** * The type strategy to use. */
private final TypeStrategy typeStrategy;
The pool strategy to use.
/** * The pool strategy to use. */
private final PoolStrategy poolStrategy;
The class file locator to use.
/** * The class file locator to use. */
private final ClassFileLocator classFileLocator;
The listener to use.
/** * The listener to use. */
private final Listener listener;
The error handler to use.
/** * The error handler to use. */
private final ErrorHandler errorHandler;
A matcher for types to exclude from transformation.
/** * A matcher for types to exclude from transformation. */
private final ElementMatcher.Junction<? super TypeDescription> ignoredTypeMatcher;
Creates a new default plugin engine that rebases types and fails fast and on unresolved types and on live initializers.
/** * Creates a new default plugin engine that rebases types and fails fast and on unresolved types and on live initializers. */
public Default() { this(new ByteBuddy()); }
Creates a new default plugin engine that rebases types and fails fast and on unresolved types and on live initializers.
Params:
  • byteBuddy – The Byte Buddy instance to use.
/** * Creates a new default plugin engine that rebases types and fails fast and on unresolved types and on live initializers. * * @param byteBuddy The Byte Buddy instance to use. */
public Default(ByteBuddy byteBuddy) { this(byteBuddy, TypeStrategy.Default.REBASE); }
Creates a new default plugin engine.
Params:
  • byteBuddy – The Byte Buddy instance to use.
  • typeStrategy – The type strategy to use.
/** * Creates a new default plugin engine. * * @param byteBuddy The Byte Buddy instance to use. * @param typeStrategy The type strategy to use. */
protected Default(ByteBuddy byteBuddy, TypeStrategy typeStrategy) { this(byteBuddy, typeStrategy, PoolStrategy.Default.FAST, ClassFileLocator.NoOp.INSTANCE, Listener.NoOp.INSTANCE, new ErrorHandler.Compound(ErrorHandler.Failing.FAIL_FAST, ErrorHandler.Enforcing.ALL_TYPES_RESOLVED, ErrorHandler.Enforcing.NO_LIVE_INITIALIZERS), none()); }
Creates a new default plugin engine.
Params:
  • byteBuddy – The Byte Buddy instance to use.
  • typeStrategy – The type strategy to use.
  • poolStrategy – The pool strategy to use.
  • classFileLocator – The class file locator to use.
  • listener – The listener to use.
  • errorHandler – The error handler to use.
  • ignoredTypeMatcher – A matcher for types to exclude from transformation.
/** * Creates a new default plugin engine. * * @param byteBuddy The Byte Buddy instance to use. * @param typeStrategy The type strategy to use. * @param poolStrategy The pool strategy to use. * @param classFileLocator The class file locator to use. * @param listener The listener to use. * @param errorHandler The error handler to use. * @param ignoredTypeMatcher A matcher for types to exclude from transformation. */
protected Default(ByteBuddy byteBuddy, TypeStrategy typeStrategy, PoolStrategy poolStrategy, ClassFileLocator classFileLocator, Listener listener, ErrorHandler errorHandler, ElementMatcher.Junction<? super TypeDescription> ignoredTypeMatcher) { this.byteBuddy = byteBuddy; this.typeStrategy = typeStrategy; this.poolStrategy = poolStrategy; this.classFileLocator = classFileLocator; this.listener = listener; this.errorHandler = errorHandler; this.ignoredTypeMatcher = ignoredTypeMatcher; }
Creates a plugin engine from an EntryPoint.
Params:
  • entryPoint – The entry point to resolve into a plugin engine.
  • classFileVersion – The class file version to assume.
  • methodNameTransformer – The method name transformer to use.
Returns:An appropriate plugin engine.
/** * Creates a plugin engine from an {@link EntryPoint}. * * @param entryPoint The entry point to resolve into a plugin engine. * @param classFileVersion The class file version to assume. * @param methodNameTransformer The method name transformer to use. * @return An appropriate plugin engine. */
public static Engine of(EntryPoint entryPoint, ClassFileVersion classFileVersion, MethodNameTransformer methodNameTransformer) { return new Default(entryPoint.byteBuddy(classFileVersion), new TypeStrategy.ForEntryPoint(entryPoint, methodNameTransformer)); }
Runs a plugin engine using the first and second argument as source and target file location and any additional argument as the fully qualified name of any plugin to apply.
Params:
  • argument – The arguments for running the plugin engine.
Throws:
/** * Runs a plugin engine using the first and second argument as source and target file location and any additional argument as * the fully qualified name of any plugin to apply. * * @param argument The arguments for running the plugin engine. * @throws ClassNotFoundException If a plugin class cannot be found on the system class loader. * @throws IOException If an I/O exception occurs. */
@SuppressWarnings("unchecked") public static void main(String... argument) throws ClassNotFoundException, IOException { if (argument.length < 2) { throw new IllegalArgumentException("Expected arguments: <source> <target> [<plugin>, ...]"); } List<Plugin.Factory> factories = new ArrayList<Factory>(argument.length - 2); for (String plugin : Arrays.asList(argument).subList(2, argument.length)) { factories.add(new Factory.UsingReflection((Class<? extends Plugin>) Class.forName(plugin))); } new Default().apply(new File(argument[0]), new File(argument[1]), factories); }
{@inheritDoc}
/** * {@inheritDoc} */
public Engine with(ByteBuddy byteBuddy) { return new Default(byteBuddy, typeStrategy, poolStrategy, classFileLocator, listener, errorHandler, ignoredTypeMatcher); }
{@inheritDoc}
/** * {@inheritDoc} */
public Engine with(TypeStrategy typeStrategy) { return new Default(byteBuddy, typeStrategy, poolStrategy, classFileLocator, listener, errorHandler, ignoredTypeMatcher); }
{@inheritDoc}
/** * {@inheritDoc} */
public Engine with(PoolStrategy poolStrategy) { return new Default(byteBuddy, typeStrategy, poolStrategy, classFileLocator, listener, errorHandler, ignoredTypeMatcher); }
{@inheritDoc}
/** * {@inheritDoc} */
public Engine with(ClassFileLocator classFileLocator) { return new Default(byteBuddy, typeStrategy, poolStrategy, new ClassFileLocator.Compound(this.classFileLocator, classFileLocator), listener, errorHandler, ignoredTypeMatcher); }
{@inheritDoc}
/** * {@inheritDoc} */
public Engine with(Listener listener) { return new Default(byteBuddy, typeStrategy, poolStrategy, classFileLocator, new Listener.Compound(this.listener, listener), errorHandler, ignoredTypeMatcher); }
{@inheritDoc}
/** * {@inheritDoc} */
public Engine withoutErrorHandlers() { return new Default(byteBuddy, typeStrategy, poolStrategy, classFileLocator, listener, Listener.NoOp.INSTANCE, ignoredTypeMatcher); }
{@inheritDoc}
/** * {@inheritDoc} */
public Engine withErrorHandlers(List<? extends ErrorHandler> errorHandlers) { return new Default(byteBuddy, typeStrategy, poolStrategy, classFileLocator, listener, new ErrorHandler.Compound(errorHandlers), ignoredTypeMatcher); }
{@inheritDoc}
/** * {@inheritDoc} */
public Engine ignore(ElementMatcher<? super TypeDescription> matcher) { return new Default(byteBuddy, typeStrategy, poolStrategy, classFileLocator, listener, errorHandler, ignoredTypeMatcher.<TypeDescription>or(matcher)); }
{@inheritDoc}
/** * {@inheritDoc} */
public Summary apply(Source source, Target target, List<? extends Plugin.Factory> factories) throws IOException { Listener listener = new Listener.Compound(this.listener, new Listener.ForErrorHandler(errorHandler)); List<TypeDescription> transformed = new ArrayList<TypeDescription>(); Map<TypeDescription, List<Throwable>> failed = new LinkedHashMap<TypeDescription, List<Throwable>>(); List<String> unresolved = new ArrayList<String>(); RuntimeException rethrown = null; List<Plugin> plugins = new ArrayList<Plugin>(factories.size()); try { for (Plugin.Factory factory : factories) { plugins.add(factory.make()); } Source.Origin origin = source.read(); try { ClassFileLocator classFileLocator = new ClassFileLocator.Compound(origin.getClassFileLocator(), this.classFileLocator); TypePool typePool = poolStrategy.typePool(classFileLocator); Manifest manifest = origin.getManifest(); listener.onManifest(manifest); Target.Sink sink = target.write(manifest); try { for (Source.Element element : origin) { String name = element.getName(); while (name.startsWith("/")) { name = name.substring(1); } if (name.endsWith(CLASS_FILE_EXTENSION)) { String typeName = name.substring(0, name.length() - CLASS_FILE_EXTENSION.length()).replace('/', '.'); listener.onDiscovery(typeName); TypePool.Resolution resolution = typePool.describe(typeName); if (resolution.isResolved()) { TypeDescription typeDescription = resolution.resolve(); if (!ignoredTypeMatcher.matches(typeDescription)) { List<Plugin> applied = new ArrayList<Plugin>(), ignored = new ArrayList<Plugin>(); List<Throwable> errored = new ArrayList<Throwable>(); DynamicType.Builder<?> builder = typeStrategy.builder(byteBuddy, typeDescription, classFileLocator); for (Plugin plugin : plugins) { try { if (plugin.matches(typeDescription)) { builder = plugin.apply(builder, typeDescription, classFileLocator); listener.onTransformation(typeDescription, plugin); applied.add(plugin); } else { listener.onIgnored(typeDescription, plugin); ignored.add(plugin); } } catch (Throwable throwable) { listener.onError(typeDescription, plugin, throwable); errored.add(throwable); } } if (!errored.isEmpty()) { listener.onError(typeDescription, errored); sink.retain(element); failed.put(typeDescription, errored); } else if (!applied.isEmpty()) { DynamicType dynamicType = builder.make(); listener.onTransformation(typeDescription, applied); for (Map.Entry<TypeDescription, LoadedTypeInitializer> entry : dynamicType.getLoadedTypeInitializers().entrySet()) { if (entry.getValue().isAlive()) { listener.onLiveInitializer(typeDescription, entry.getKey()); } } sink.store(dynamicType.getAllTypes()); transformed.add(dynamicType.getTypeDescription()); } else { listener.onIgnored(typeDescription, ignored); sink.retain(element); } } else { listener.onIgnored(typeDescription, plugins); sink.retain(element); } listener.onComplete(typeDescription); } else { listener.onUnresolved(typeName); sink.retain(element); unresolved.add(typeName); } } else if (!name.equals(JarFile.MANIFEST_NAME)) { listener.onResource(name); sink.retain(element); } } if (!failed.isEmpty()) { listener.onError(failed); } } finally { sink.close(); } } finally { origin.close(); } } finally { for (Plugin plugin : plugins) { try { plugin.close(); } catch (Throwable throwable) { try { listener.onError(plugin, throwable); } catch (RuntimeException exception) { rethrown = rethrown == null ? exception : rethrown; } } } } if (rethrown == null) { return new Summary(transformed, failed, unresolved); } else { throw rethrown; } } } }
A non-operational plugin that does not instrument any type. This plugin does not need to be closed.
/** * A non-operational plugin that does not instrument any type. This plugin does not need to be closed. */
@HashCodeAndEqualsPlugin.Enhance class NoOp implements Plugin, Plugin.Factory {
{@inheritDoc}
/** * {@inheritDoc} */
public Plugin make() { return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean matches(TypeDescription target) { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) { throw new IllegalStateException("Cannot apply non-operational plugin"); }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() { /* do nothing */ } }
An abstract base for a Plugin that matches types by a given ElementMatcher.
/** * An abstract base for a {@link Plugin} that matches types by a given {@link ElementMatcher}. */
@HashCodeAndEqualsPlugin.Enhance abstract class ForElementMatcher implements Plugin {
The element matcher to apply.
/** * The element matcher to apply. */
private final ElementMatcher<? super TypeDescription> matcher;
Creates a new plugin that matches types using an element matcher.
Params:
  • matcher – The element matcher to apply.
/** * Creates a new plugin that matches types using an element matcher. * * @param matcher The element matcher to apply. */
protected ForElementMatcher(ElementMatcher<? super TypeDescription> matcher) { this.matcher = matcher; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean matches(TypeDescription target) { return matcher.matches(target); } }
A compound plugin that applies several plugins in a row.
/** * A compound plugin that applies several plugins in a row. */
@HashCodeAndEqualsPlugin.Enhance class Compound implements Plugin {
The plugins to apply.
/** * The plugins to apply. */
private final List<Plugin> plugins;
Creates a compound plugin.
Params:
  • plugin – The plugins to apply.
/** * Creates a compound plugin. * * @param plugin The plugins to apply. */
public Compound(Plugin... plugin) { this(Arrays.asList(plugin)); }
Creates a compound plugin.
Params:
  • plugins – The plugins to apply.
/** * Creates a compound plugin. * * @param plugins The plugins to apply. */
public Compound(List<? extends Plugin> plugins) { this.plugins = new ArrayList<Plugin>(); for (Plugin plugin : plugins) { if (plugin instanceof Compound) { this.plugins.addAll(((Compound) plugin).plugins); } else if (!(plugin instanceof NoOp)) { this.plugins.add(plugin); } } }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean matches(TypeDescription target) { for (Plugin plugin : plugins) { if (plugin.matches(target)) { return true; } } return false; }
{@inheritDoc}
/** * {@inheritDoc} */
public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) { for (Plugin plugin : plugins) { if (plugin.matches(typeDescription)) { builder = plugin.apply(builder, typeDescription, classFileLocator); } } return builder; }
{@inheritDoc}
/** * {@inheritDoc} */
public void close() throws IOException { for (Plugin plugin : plugins) { plugin.close(); } } } }