1 /*
2  * Copyright 2014 - 2020 Rafael Winterhalter
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.bytebuddy.implementation;
17
18 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
19 import net.bytebuddy.description.field.FieldDescription;
20 import net.bytebuddy.description.method.MethodDescription;
21 import net.bytebuddy.description.method.MethodList;
22 import net.bytebuddy.description.type.TypeDefinition;
23 import net.bytebuddy.description.type.TypeDescription;
24 import net.bytebuddy.dynamic.scaffold.FieldLocator;
25 import net.bytebuddy.dynamic.scaffold.InstrumentedType;
26 import net.bytebuddy.dynamic.scaffold.MethodGraph;
27 import net.bytebuddy.implementation.bind.MethodDelegationBinder;
28 import net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder;
29 import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
30 import net.bytebuddy.implementation.bytecode.Duplication;
31 import net.bytebuddy.implementation.bytecode.StackManipulation;
32 import net.bytebuddy.implementation.bytecode.TypeCreation;
33 import net.bytebuddy.implementation.bytecode.assign.Assigner;
34 import net.bytebuddy.implementation.bytecode.member.FieldAccess;
35 import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
36 import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
37 import net.bytebuddy.matcher.ElementMatcher;
38 import net.bytebuddy.utility.CompoundList;
39 import net.bytebuddy.utility.RandomString;
40 import net.bytebuddy.jar.asm.MethodVisitor;
41 import net.bytebuddy.jar.asm.Opcodes;
42
43 import java.lang.reflect.Type;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.Collections;
47 import java.util.List;
48
49 import static net.bytebuddy.matcher.ElementMatchers.*;
50
51 /**
52  * This implementation delegates an method call to another method which can either be {@code static} by providing
53  * a reference to a {@link java.lang.Class} or an instance method when another object is provided. The potential
54  * targets of the method delegation can further be filtered by applying a filter. The method delegation can be
55  * customized by invoking the {@code MethodDelegation}'s several builder methods.
56  * <h3>Without any customization, the method delegation will work as follows:</h3>
57  * <span style="text-decoration: underline">Binding an instrumented method to a given delegate method</span>
58  * <p>&nbsp;</p>
59  * A method will be bound parameter by parameter. Considering a method {@code Foo#bar} being bound to a method
60  * {@code Qux#baz}, the method delegation will be decided on basis of the following annotations:
61  * <ul>
62  * <li>{@link net.bytebuddy.implementation.bind.annotation.Argument}:
63  * This annotation will bind the {@code n}-th parameter of {@code Foo#bar} to that parameter of {@code Qux#baz}that
64  * is annotated with this annotation where {@code n} is the obligatory argument of the {@code @Argument} annotation.</li>
65  * <li>{@link net.bytebuddy.implementation.bind.annotation.AllArguments}:
66  * This annotation will assign a collection of all parameters of {@code Foo#bar} to that parameter of {@code Qux#baz}
67  * that is annotated with {@code AllArguments}.</li>
68  * <li>{@link net.bytebuddy.implementation.bind.annotation.This}: A parameter
69  * of {@code Qux#baz} that is annotated with {@code This} will be assigned the instance that is instrumented for
70  * a non-static method.</li>
71  * <li>{@link net.bytebuddy.implementation.bind.annotation.Super}: A parameter that is annotated with
72  * this annotation is assigned a proxy that allows calling an instrumented type's super methods.</li>
73  * <li>{@link net.bytebuddy.implementation.bind.annotation.Default}: A parameter that is annotated with
74  * this annotation is assigned a proxy that allows calling an instrumented type's directly implemented interfaces'
75  * default methods.</li>
76  * <li>{@link net.bytebuddy.implementation.bind.annotation.SuperCall}: A parameter
77  * of {@code Qux#baz} that is annotated with {@code SuperCall} will be assigned an instance of a type implementing both
78  * {@link java.lang.Runnable} and {@link java.util.concurrent.Callable} which will invoke the instrumented method on the
79  * invocation of either interface's method. The call is made using the original arguments of the method invocation.
80  * The return value is only emitted for the {@link java.util.concurrent.Callable#call()} method which additionally
81  * requires to catch any unchecked exceptions that might be thrown by the original method's implementation. If a
82  * source method is abstract, using this annotation excludes the method with this parameter annotation from being bound
83  * to this source method.
84  * </li>
85  * <li>{@link net.bytebuddy.implementation.bind.annotation.DefaultCall}:
86  * This annotation is similar to the {@link net.bytebuddy.implementation.bind.annotation.SuperCall}
87  * annotation but it invokes a default method that is compatible to this method. If a source method does not represent
88  * a default method, using this annotation excludes the method with this parameter annotation from being bound to this
89  * source method.</li>
90  * <li>The {@link net.bytebuddy.implementation.bind.annotation.SuperMethod} or
91  * {@link net.bytebuddy.implementation.bind.annotation.DefaultMethod} annotations can be used on any parameter type
92  * that is assignable from the {@link java.lang.reflect.Method} type. the parameter is bound a method instance that
93  * allows for the reflective invocation of a super or default method. Note that this method is not equal to the intercepted
94  * method but represents a synthetic accessor method. Using this annotation also causes this accessor to be {@code public}
95  * which allows its outside invocation without any access checks by a security manager.</li>
96  * <li>{@link net.bytebuddy.implementation.bind.annotation.Origin}: A parameter of
97  * {@code Qux#baz} that is annotated with {@code Origin} is assigned a reference to either a {@link java.lang.reflect.Method},
98  * a {@link java.lang.reflect.Constructor}, a {@code java.lang.reflect.Executable} or a {@link java.lang.Class} instance.
99  * A {@code Method}-typed, {@code Constructor} or {@code Executable} parameter is assigned a reference to the original
100  * method that is instrumented. A {@code Class}-typed parameter is assigned the type of the caller. Furthermore, {@code MethodType}
101  * and {@code MethodHandle} parameters are also supported. When using the annotation on a {@link java.lang.String} type,
102  * the intercepted method's {@code toString} value is injected. The same holds for a parameter of type {@code int} that receives
103  * the modifiers of the instrumented method.</li>
104  * <li>{@link net.bytebuddy.implementation.bind.annotation.StubValue}: Assigns the (boxed) default value of the
105  * intercepted method's return type to the parameter. If the return type is {@code void}, {@code null} is assigned.</li>
106  * <li>{@link net.bytebuddy.implementation.bind.annotation.Empty}: Assigns the parameter type's
107  * default value, i.e. {@code nullfor a reference type or zero for primitive types. This is an opportunity to
108  * ignore a parameter.</li>
109  * <li>{@link net.bytebuddy.implementation.bind.annotation.Pipe}: A parameter that is annotated
110  * with this annotation is assigned a proxy for forwarding the source method invocation to another instance of the
111  * same type as the declaring type of the intercepted method. <b>This annotation needs to be installed and explicitly
112  * registered before it can be used.</b> See the {@link net.bytebuddy.implementation.bind.annotation.Pipe}
113  * annotation's documentation for further information on how this can be done.</li>
114  * <li>{@link net.bytebuddy.implementation.bind.annotation.Morph}: The morph annotation is similar to
115  * the {@link net.bytebuddy.implementation.bind.annotation.SuperCall} annotation but allows to
116  * explicitly define and therewith alter the arguments that are handed to the super method. <b>This annotation needs
117  * to be installed and explicitly registered before it can be used.</b> See the documentation to the annotation for
118  * further information.</li>
119  * <li>{@link net.bytebuddy.implementation.bind.annotation.FieldValue}: Allows to access a field's value at the time
120  * of the method invocation. The field's value is directly assigned to the annotated parameter.</li>
121  * <li>{@link net.bytebuddy.implementation.bind.annotation.FieldProxy}: Allows to access fields via getter
122  * and setter proxies. <b>This annotation needs to be installed and explicitly registered before it can be used.</b>
123  * Note that any field access requires boxing such that a use of {@link net.bytebuddy.implementation.FieldAccessor} in
124  * combination with {@link net.bytebuddy.implementation.MethodDelegation#andThen(Implementation)} might be a more
125  * performant alternative for implementing field getters and setters.</li>
126  * </ul>
127  * If a method is not annotated with any of the above methods, it will be treated as if it was annotated
128  * {@link net.bytebuddy.implementation.bind.annotation.Argument} using the next
129  * unbound parameter index of the source method as its parameter. This means that a method
130  * {@code Qux#baz(@Argument(2) Object p1, Object p2, @Argument(0) Object p3} would be treated as if {@code p2} was annotated
131  * with {@code @Argument(1)}.
132  * <p>&nbsp;</p>
133  * In addition, the {@link net.bytebuddy.implementation.bind.annotation.RuntimeType}
134  * annotation can instruct a parameter to be bound by a
135  * {@link net.bytebuddy.implementation.bytecode.assign.Assigner} with considering the
136  * runtime type of the parameter.
137  * <p>&nbsp;</p>
138  * <span style="text-decoration: underline">Selecting among different methods that can be used for binding a method
139  * of the instrumented type</span>
140  * <p>&nbsp;</p>
141  * When deciding between two methods {@code Foo#bar} and {@code Foo#qux} that could both be used to delegating a
142  * method call, the following consideration is applied in the given order:
143  * <ol>
144  * <li>{@link net.bytebuddy.implementation.bind.annotation.BindingPriority}:
145  * A method that is annotated with this annotation is given a specific priority where the default priority is set
146  * to {@link net.bytebuddy.implementation.bind.annotation.BindingPriority#DEFAULT}
147  * for non-annotated method. A method with a higher priority is considered a better target for delegation.</li>
148  * <li>{@link net.bytebuddy.implementation.bind.DeclaringTypeResolver}:
149  * If a target method is declared by a more specific type than another method, the method with the most specific
150  * type is bound.</li>
151  * <li>{@link net.bytebuddy.implementation.bind.MethodNameEqualityResolver}:
152  * If a source method {@code Baz#qux} is the source method, it will rather be assigned to {@code Foo#qux} because
153  * of their equal names. Similar names and case-insensitive equality are not considered.</li>
154  * <li>{@link net.bytebuddy.implementation.bind.ArgumentTypeResolver}:
155  * The most specific type resolver will consider all bindings that are using the
156  * {@link net.bytebuddy.implementation.bind.annotation.Argument}
157  * annotation for resolving a binding conflict. In this context, the resolution will equal the most-specific
158  * type resolution that is performed by the Java compiler. This means that a source method {@code Bar#baz(String)}
159  * will rather be bound to a method {@code Foo#bar(String)} than {@code Foo#qux(Object)} because the {@code String}
160  * type is more specific than the {@code Object} type. If two methods are equally adequate by their parameter types,
161  * then the method with the higher numbers of {@code @Argument} annotated parameters is considered as the better
162  * delegation target.</li>
163  * <li>{@link net.bytebuddy.implementation.bind.ParameterLengthResolver}:
164  * If a target methods has a higher number of total parameters that were successfully bound, the method with
165  * the higher number will be considered as the better delegation target.</li>
166  * </ol>
167  * <p>
168  * Additionally, if a method is annotated by
169  * {@link net.bytebuddy.implementation.bind.annotation.IgnoreForBinding},
170  * it is never considered as a target for a method delegation.
171  * </p>
172  * <p>
173  * <b>Important</b>: For invoking a method on another instance, use the {@link MethodCall} implementation. A method delegation
174  * intends to bind a interceptor class and its resolution algorithm will not necessarily yield a delegation to the intercepted
175  * method.
176  * </p>
177  *
178  * @see MethodCall
179  * @see net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder.ForFixedValue
180  */

181 @HashCodeAndEqualsPlugin.Enhance
182 public class MethodDelegation implements Implementation.Composable {
183
184     /**
185      * The implementation delegate for this method delegation.
186      */

187     private final ImplementationDelegate implementationDelegate;
188
189     /**
190      * A list of {@link net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder}s
191      * to be used by this method delegation.
192      */

193     private final List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
194
195     /**
196      * The {@link net.bytebuddy.implementation.bind.MethodDelegationBinder.AmbiguityResolver}
197      * to be used by this method delegation.
198      */

199     private final MethodDelegationBinder.AmbiguityResolver ambiguityResolver;
200
201     /**
202      * The termination handler to apply.
203      */

204     private final TargetMethodAnnotationDrivenBinder.TerminationHandler terminationHandler;
205
206     /**
207      * The binding resolver being used to select the relevant method binding.
208      */

209     private final MethodDelegationBinder.BindingResolver bindingResolver;
210
211     /**
212      * The {@link net.bytebuddy.implementation.bytecode.assign.Assigner} to be used by this method delegation.
213      */

214     private final Assigner assigner;
215
216     /**
217      * Creates a new method delegation.
218      *
219      * @param implementationDelegate The implementation delegate to use by this method delegator.
220      * @param parameterBinders       The parameter binders to use by this method delegator.
221      * @param ambiguityResolver      The ambiguity resolver to use by this method delegator.
222      * @param bindingResolver        The binding resolver being used to select the relevant method binding.
223      */

224     protected MethodDelegation(ImplementationDelegate implementationDelegate,
225                                List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
226                                MethodDelegationBinder.AmbiguityResolver ambiguityResolver,
227                                MethodDelegationBinder.BindingResolver bindingResolver) {
228         this(implementationDelegate,
229                 parameterBinders,
230                 ambiguityResolver,
231                 MethodDelegationBinder.TerminationHandler.Default.RETURNING,
232                 bindingResolver,
233                 Assigner.DEFAULT);
234     }
235
236     /**
237      * Creates a new method delegation.
238      *
239      * @param implementationDelegate The implementation delegate to use by this method delegator.
240      * @param parameterBinders       The parameter binders to use by this method delegator.
241      * @param ambiguityResolver      The ambiguity resolver to use by this method delegator.
242      * @param terminationHandler     The termination handler to apply.
243      * @param bindingResolver        The binding resolver being used to select the relevant method binding.
244      * @param assigner               The assigner to be supplied by this method delegator.
245      */

246     private MethodDelegation(ImplementationDelegate implementationDelegate,
247                              List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
248                              MethodDelegationBinder.AmbiguityResolver ambiguityResolver,
249                              TargetMethodAnnotationDrivenBinder.TerminationHandler terminationHandler,
250                              MethodDelegationBinder.BindingResolver bindingResolver,
251                              Assigner assigner) {
252         this.implementationDelegate = implementationDelegate;
253         this.parameterBinders = parameterBinders;
254         this.terminationHandler = terminationHandler;
255         this.ambiguityResolver = ambiguityResolver;
256         this.bindingResolver = bindingResolver;
257         this.assigner = assigner;
258     }
259
260     /**
261      * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered
262      * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if
263      * the target type is either public or in the same package as the instrumented type and if the target method is either public
264      * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if
265      * the interception is targeting the instrumented type.
266      *
267      * @param type The target type for the delegation.
268      * @return A method delegation that redirects method calls to a static method of the supplied type.
269      */

270     public static MethodDelegation to(Class<?> type) {
271         return withDefaultConfiguration().to(type);
272     }
273
274     /**
275      * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered
276      * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if
277      * the target type is either public or in the same package as the instrumented type and if the target method is either public
278      * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if
279      * the interception is targeting the instrumented type.
280      *
281      * @param typeDescription The target type for the delegation.
282      * @return A method delegation that redirects method calls to a static method of the supplied type.
283      */

284     public static MethodDelegation to(TypeDescription typeDescription) {
285         return withDefaultConfiguration().to(typeDescription);
286     }
287
288     /**
289      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
290      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
291      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
292      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
293      * a delegation target if the delegation is targeting the instrumented type.
294      *
295      * @param target The target instance for the delegation.
296      * @return A method delegation that redirects method calls to a static method of the supplied type.
297      */

298     public static MethodDelegation to(Object target) {
299         return withDefaultConfiguration().to(target);
300     }
301
302     /**
303      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
304      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
305      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
306      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
307      * a delegation target if the delegation is targeting the instrumented type.
308      *
309      * @param target              The target instance for the delegation.
310      * @param methodGraphCompiler The method graph compiler to use.
311      * @return A method delegation that redirects method calls to a static method of the supplied type.
312      */

313     public static MethodDelegation to(Object target, MethodGraph.Compiler methodGraphCompiler) {
314         return withDefaultConfiguration().to(target, methodGraphCompiler);
315     }
316
317     /**
318      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
319      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
320      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
321      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
322      * a delegation target if the delegation is targeting the instrumented type.
323      *
324      * @param target    The target instance for the delegation.
325      * @param fieldName The name of the field that is holding the {@code target} instance.
326      * @return A method delegation that redirects method calls to a static method of the supplied type.
327      */

328     public static MethodDelegation to(Object target, String fieldName) {
329         return withDefaultConfiguration().to(target, fieldName);
330     }
331
332     /**
333      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
334      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
335      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
336      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
337      * a delegation target if the delegation is targeting the instrumented type.
338      *
339      * @param target              The target instance for the delegation.
340      * @param fieldName           The name of the field that is holding the {@code target} instance.
341      * @param methodGraphCompiler The method graph compiler to use.
342      * @return A method delegation that redirects method calls to a static method of the supplied type.
343      */

344     public static MethodDelegation to(Object target, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
345         return withDefaultConfiguration().to(target, fieldName, methodGraphCompiler);
346     }
347
348     /**
349      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
350      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
351      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
352      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
353      * a delegation target if the delegation is targeting the instrumented type.
354      *
355      * @param target The target instance for the delegation.
356      * @param type   The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
357      * @return A method delegation that redirects method calls to a static method of the supplied type.
358      */

359     public static MethodDelegation to(Object target, Type type) {
360         return withDefaultConfiguration().to(target, type);
361     }
362
363     /**
364      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
365      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
366      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
367      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
368      * a delegation target if the delegation is targeting the instrumented type.
369      *
370      * @param target              The target instance for the delegation.
371      * @param type                The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
372      * @param methodGraphCompiler The method graph compiler to use.
373      * @return A method delegation that redirects method calls to a static method of the supplied type.
374      */

375     public static MethodDelegation to(Object target, Type type, MethodGraph.Compiler methodGraphCompiler) {
376         return withDefaultConfiguration().to(target, type, methodGraphCompiler);
377     }
378
379     /**
380      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
381      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
382      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
383      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
384      * a delegation target if the delegation is targeting the instrumented type.
385      *
386      * @param target    The target instance for the delegation.
387      * @param type      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
388      * @param fieldName The name of the field that is holding the {@code target} instance.
389      * @return A method delegation that redirects method calls to a static method of the supplied type.
390      */

391     public static MethodDelegation to(Object target, Type type, String fieldName) {
392         return withDefaultConfiguration().to(target, type, fieldName);
393     }
394
395     /**
396      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
397      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
398      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
399      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
400      * a delegation target if the delegation is targeting the instrumented type.
401      *
402      * @param target              The target instance for the delegation.
403      * @param type                The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
404      * @param fieldName           The name of the field that is holding the {@code target} instance.
405      * @param methodGraphCompiler The method graph compiler to use.
406      * @return A method delegation that redirects method calls to a static method of the supplied type.
407      */

408     public static MethodDelegation to(Object target, Type type, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
409         return withDefaultConfiguration().to(target, type, fieldName, methodGraphCompiler);
410     }
411
412     /**
413      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
414      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
415      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
416      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
417      * a delegation target if the delegation is targeting the instrumented type.
418      *
419      * @param target         The target instance for the delegation.
420      * @param typeDefinition The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
421      * @return A method delegation that redirects method calls to a static method of the supplied type.
422      */

423     public static MethodDelegation to(Object target, TypeDefinition typeDefinition) {
424         return withDefaultConfiguration().to(target, typeDefinition);
425     }
426
427     /**
428      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
429      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
430      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
431      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
432      * a delegation target if the delegation is targeting the instrumented type.
433      *
434      * @param target              The target instance for the delegation.
435      * @param typeDefinition      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
436      * @param methodGraphCompiler The method graph compiler to use.
437      * @return A method delegation that redirects method calls to a static method of the supplied type.
438      */

439     public static MethodDelegation to(Object target, TypeDefinition typeDefinition, MethodGraph.Compiler methodGraphCompiler) {
440         return withDefaultConfiguration().to(target, typeDefinition, methodGraphCompiler);
441     }
442
443     /**
444      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
445      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
446      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
447      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
448      * a delegation target if the delegation is targeting the instrumented type.
449      *
450      * @param target         The target instance for the delegation.
451      * @param typeDefinition The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
452      * @param fieldName      The name of the field that is holding the {@code target} instance.
453      * @return A method delegation that redirects method calls to a static method of the supplied type.
454      */

455     public static MethodDelegation to(Object target, TypeDefinition typeDefinition, String fieldName) {
456         return withDefaultConfiguration().to(target, typeDefinition, fieldName);
457     }
458
459     /**
460      * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
461      * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
462      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
463      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
464      * a delegation target if the delegation is targeting the instrumented type.
465      *
466      * @param target              The target instance for the delegation.
467      * @param typeDefinition      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
468      * @param fieldName           The name of the field that is holding the {@code target} instance.
469      * @param methodGraphCompiler The method graph compiler to use.
470      * @return A method delegation that redirects method calls to a static method of the supplied type.
471      */

472     public static MethodDelegation to(Object target, TypeDefinition typeDefinition, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
473         return withDefaultConfiguration().to(target, typeDefinition, fieldName, methodGraphCompiler);
474     }
475
476     /**
477      * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target,
478      * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is
479      * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in
480      * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is
481      * targeting the instrumented type.
482      *
483      * @param type The type to construct.
484      * @return A delegation that redirects method calls to a constructor of the supplied type.
485      */

486     public static MethodDelegation toConstructor(Class<?> type) {
487         return withDefaultConfiguration().toConstructor(type);
488     }
489
490     /**
491      * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target,
492      * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is
493      * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in
494      * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is
495      * targeting the instrumented type.
496      *
497      * @param typeDescription The type to construct.
498      * @return A delegation that redirects method calls to a constructor of the supplied type.
499      */

500     public static MethodDelegation toConstructor(TypeDescription typeDescription) {
501         return withDefaultConfiguration().toConstructor(typeDescription);
502     }
503
504     /**
505      * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
506      * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
507      * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
508      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
509      * a delegation target if the delegation is targeting the instrumented type.
510      *
511      * @param name The field's name.
512      * @return A delegation that redirects invocations to a method of the specified field's instance.
513      */

514     public static MethodDelegation toField(String name) {
515         return withDefaultConfiguration().toField(name);
516     }
517
518     /**
519      * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
520      * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
521      * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
522      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
523      * a delegation target if the delegation is targeting the instrumented type.
524      *
525      * @param name                The field's name.
526      * @param fieldLocatorFactory The field locator factory to use.
527      * @return A delegation that redirects invocations to a method of the specified field's instance.
528      */

529     public static MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory) {
530         return withDefaultConfiguration().toField(name, fieldLocatorFactory);
531     }
532
533     /**
534      * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
535      * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
536      * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
537      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
538      * a delegation target if the delegation is targeting the instrumented type.
539      *
540      * @param name                The field's name.
541      * @param methodGraphCompiler The method graph compiler to use.
542      * @return A delegation that redirects invocations to a method of the specified field's instance.
543      */

544     public static MethodDelegation toField(String name, MethodGraph.Compiler methodGraphCompiler) {
545         return withDefaultConfiguration().toField(name, methodGraphCompiler);
546     }
547
548     /**
549      * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
550      * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
551      * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
552      * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
553      * a delegation target if the delegation is targeting the instrumented type.
554      *
555      * @param name                The field's name.
556      * @param fieldLocatorFactory The field locator factory to use.
557      * @param methodGraphCompiler The method graph compiler to use.
558      * @return A delegation that redirects invocations to a method of the specified field's instance.
559      */

560     public static MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory, MethodGraph.Compiler methodGraphCompiler) {
561         return withDefaultConfiguration().toField(name, fieldLocatorFactory, methodGraphCompiler);
562     }
563
564     /**
565      * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the
566      * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
567      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if
568      * the method is either public or non-private and in the same package as the instrumented type. Private methods can only
569      * be used as a delegation target if the delegation is targeting the instrumented type.
570      *
571      * @param name The name of the method that returns the delegation target.
572      * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
573      */

574     public static MethodDelegation toMethodReturnOf(String name) {
575         return withDefaultConfiguration().toMethodReturnOf(name);
576     }
577
578     /**
579      * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the
580      * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
581      * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if
582      * the method is either public or non-private and in the same package as the instrumented type. Private methods can only
583      * be used as a delegation target if the delegation is targeting the instrumented type.
584      *
585      * @param name                The name of the method that returns the delegation target.
586      * @param methodGraphCompiler The method graph compiler to use.
587      * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
588      */

589     public static MethodDelegation toMethodReturnOf(String name, MethodGraph.Compiler methodGraphCompiler) {
590         return withDefaultConfiguration().toMethodReturnOf(name, methodGraphCompiler);
591     }
592
593     /**
594      * Creates a configuration builder for a method delegation that is pre-configured with the ambiguity resolvers defined by
595      * {@link net.bytebuddy.implementation.bind.MethodDelegationBinder.AmbiguityResolver#DEFAULT} and the parameter binders
596      * defined by {@link net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder#DEFAULTS}.
597      *
598      * @return A method delegation configuration with pre-configuration.
599      */

600     public static WithCustomProperties withDefaultConfiguration() {
601         return new WithCustomProperties(MethodDelegationBinder.AmbiguityResolver.DEFAULT, TargetMethodAnnotationDrivenBinder.ParameterBinder.DEFAULTS);
602     }
603
604     /**
605      * Creates a configuration builder for a method delegation that does not apply any pre-configured
606      * {@link net.bytebuddy.implementation.bind.MethodDelegationBinder.AmbiguityResolver}s or
607      * {@link net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder}s.
608      *
609      * @return A method delegation configuration without any pre-configuration.
610      */

611     public static WithCustomProperties withEmptyConfiguration() {
612         return new WithCustomProperties(MethodDelegationBinder.AmbiguityResolver.NoOp.INSTANCE, Collections.<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>>emptyList());
613     }
614
615     /**
616      * Applies an assigner to the method delegation that is used for assigning method return and parameter types.
617      *
618      * @param assigner The assigner to apply.
619      * @return A method delegation implementation that makes use of the given designer.
620      */

621     public Implementation.Composable withAssigner(Assigner assigner) {
622         return new MethodDelegation(implementationDelegate,
623                 parameterBinders,
624                 ambiguityResolver,
625                 terminationHandler,
626                 bindingResolver,
627                 assigner);
628     }
629
630     /**
631      * {@inheritDoc}
632      */

633     public Implementation andThen(Implementation implementation) {
634         return new Compound(new MethodDelegation(implementationDelegate,
635                 parameterBinders,
636                 ambiguityResolver,
637                 MethodDelegationBinder.TerminationHandler.Default.DROPPING,
638                 bindingResolver,
639                 assigner), implementation);
640     }
641
642     /**
643      * {@inheritDoc}
644      */

645     public Composable andThen(Composable implementation) {
646         return new Compound.Composable(new MethodDelegation(implementationDelegate,
647                 parameterBinders,
648                 ambiguityResolver,
649                 MethodDelegationBinder.TerminationHandler.Default.DROPPING,
650                 bindingResolver,
651                 assigner), implementation);
652     }
653
654     /**
655      * {@inheritDoc}
656      */

657     public InstrumentedType prepare(InstrumentedType instrumentedType) {
658         return implementationDelegate.prepare(instrumentedType);
659     }
660
661     /**
662      * {@inheritDoc}
663      */

664     public ByteCodeAppender appender(Target implementationTarget) {
665         ImplementationDelegate.Compiled compiled = implementationDelegate.compile(implementationTarget.getInstrumentedType());
666         return new Appender(implementationTarget,
667                 new MethodDelegationBinder.Processor(compiled.getRecords(), ambiguityResolver, bindingResolver),
668                 terminationHandler,
669                 assigner,
670                 compiled);
671     }
672
673     /**
674      * An implementation delegate is responsible for executing the actual method delegation and for resolving the target methods.
675      */

676     protected interface ImplementationDelegate extends InstrumentedType.Prepareable {
677
678         /**
679          * A name prefix for fields.
680          */

681         String FIELD_NAME_PREFIX = "delegate";
682
683         /**
684          * Compiles this implementation delegate.
685          *
686          * @param instrumentedType The instrumented type.
687          * @return A compiled implementation delegate.
688          */

689         Compiled compile(TypeDescription instrumentedType);
690
691         /**
692          * A compiled implementation delegate.
693          */

694         interface Compiled {
695
696             /**
697              * Resolves a stack manipulation that prepares the delegation invocation.
698              *
699              * @param instrumentedMethod The instrumented method.
700              * @return A stack manipulation that is applied prior to loading arguments and executing the method call.
701              */

702             StackManipulation prepare(MethodDescription instrumentedMethod);
703
704             /**
705              * Resolves an invoker to use for invoking the delegation target.
706              *
707              * @return The method invoker to use.
708              */

709             MethodDelegationBinder.MethodInvoker invoke();
710
711             /**
712              * Returns a list of binding records to consider for delegation.
713              *
714              * @return A list of delegation binder records to consider.
715              */

716             List<MethodDelegationBinder.Record> getRecords();
717
718             /**
719              * A compiled implementation delegate for invoking a static method.
720              */

721             @HashCodeAndEqualsPlugin.Enhance
722             class ForStaticCall implements Compiled {
723
724                 /**
725                  * The list of records to consider.
726                  */

727                 private final List<MethodDelegationBinder.Record> records;
728
729                 /**
730                  * Creates a new compiled implementation delegate for a static method call.
731                  *
732                  * @param records The list of records to consider.
733                  */

734                 protected ForStaticCall(List<MethodDelegationBinder.Record> records) {
735                     this.records = records;
736                 }
737
738                 /**
739                  * {@inheritDoc}
740                  */

741                 public StackManipulation prepare(MethodDescription instrumentedMethod) {
742                     return StackManipulation.Trivial.INSTANCE;
743                 }
744
745                 /**
746                  * {@inheritDoc}
747                  */

748                 public MethodDelegationBinder.MethodInvoker invoke() {
749                     return MethodDelegationBinder.MethodInvoker.Simple.INSTANCE;
750                 }
751
752                 /**
753                  * {@inheritDoc}
754                  */

755                 public List<MethodDelegationBinder.Record> getRecords() {
756                     return records;
757                 }
758             }
759
760             /**
761              * A compiled implementation delegate that invokes methods on a field.
762              */

763             @HashCodeAndEqualsPlugin.Enhance
764             class ForField implements Compiled {
765
766                 /**
767                  * The field to delegate to.
768                  */

769                 private final FieldDescription fieldDescription;
770
771                 /**
772                  * The records to consider for delegation.
773                  */

774                 private final List<MethodDelegationBinder.Record> records;
775
776                 /**
777                  * Creates a new compiled implementation delegate for a field delegation.
778                  *
779                  * @param fieldDescription The field to delegate to.
780                  * @param records          The records to consider for delegation.
781                  */

782                 protected ForField(FieldDescription fieldDescription, List<MethodDelegationBinder.Record> records) {
783                     this.fieldDescription = fieldDescription;
784                     this.records = records;
785                 }
786
787                 /**
788                  * {@inheritDoc}
789                  */

790                 public StackManipulation prepare(MethodDescription instrumentedMethod) {
791                     if (instrumentedMethod.isStatic() && !fieldDescription.isStatic()) {
792                         throw new IllegalStateException("Cannot read " + fieldDescription + " from " + instrumentedMethod);
793                     }
794                     return new StackManipulation.Compound(fieldDescription.isStatic()
795                             ? StackManipulation.Trivial.INSTANCE
796                             : MethodVariableAccess.loadThis(), FieldAccess.forField(fieldDescription).read());
797                 }
798
799                 /**
800                  * {@inheritDoc}
801                  */

802                 public MethodDelegationBinder.MethodInvoker invoke() {
803                     return new MethodDelegationBinder.MethodInvoker.Virtual(fieldDescription.getType().asErasure());
804                 }
805
806                 /**
807                  * {@inheritDoc}
808                  */

809                 public List<MethodDelegationBinder.Record> getRecords() {
810                     return records;
811                 }
812             }
813
814             /**
815              * A compiled implementation delegate that invokes a method on an instance that is returned by another method.
816              */

817             @HashCodeAndEqualsPlugin.Enhance
818             class ForMethodReturn implements Compiled {
819
820                 /**
821                  * The method to call for result.
822                  */

823                 private final MethodDescription methodDescription;
824
825                 /**
826                  * The records to consider for delegation.
827                  */

828                 private final List<MethodDelegationBinder.Record> records;
829
830                 /**
831                  * Creates a new compiled implementation delegate for a field delegation.
832                  *
833                  * @param methodDescription The method to call for result.
834                  * @param records           The records to consider for delegation.
835                  */

836                 protected ForMethodReturn(MethodDescription methodDescription, List<MethodDelegationBinder.Record> records) {
837                     this.methodDescription = methodDescription;
838                     this.records = records;
839                 }
840
841                 /**
842                  * {@inheritDoc}
843                  */

844                 public StackManipulation prepare(MethodDescription instrumentedMethod) {
845                     if (instrumentedMethod.isStatic() && !methodDescription.isStatic()) {
846                         throw new IllegalStateException("Cannot invoke " + methodDescription + " from " + instrumentedMethod);
847                     }
848                     return new StackManipulation.Compound(methodDescription.isStatic()
849                             ? StackManipulation.Trivial.INSTANCE
850                             : MethodVariableAccess.loadThis(), MethodInvocation.invoke(methodDescription));
851                 }
852
853                 /**
854                  * {@inheritDoc}
855                  */

856                 public MethodDelegationBinder.MethodInvoker invoke() {
857                     return new MethodDelegationBinder.MethodInvoker.Virtual(methodDescription.getReturnType().asErasure());
858                 }
859
860                 /**
861                  * {@inheritDoc}
862                  */

863                 public List<MethodDelegationBinder.Record> getRecords() {
864                     return records;
865                 }
866             }
867
868             /**
869              * A compiled implementation delegate for a constructor delegation.
870              */

871             @HashCodeAndEqualsPlugin.Enhance
872             class ForConstruction implements Compiled {
873
874                 /**
875                  * The type to be constructed.
876                  */

877                 private final TypeDescription typeDescription;
878
879                 /**
880                  * The records to consider for delegation.
881                  */

882                 private final List<MethodDelegationBinder.Record> records;
883
884                 /**
885                  * Creates a new compiled implementation delegate for a constructor delegation.
886                  *
887                  * @param typeDescription The type to be constructed.
888                  * @param records         The records to consider for delegation.
889                  */

890                 protected ForConstruction(TypeDescription typeDescription, List<MethodDelegationBinder.Record> records) {
891                     this.typeDescription = typeDescription;
892                     this.records = records;
893                 }
894
895                 /**
896                  * {@inheritDoc}
897                  */

898                 public StackManipulation prepare(MethodDescription instrumentedMethod) {
899                     return new StackManipulation.Compound(TypeCreation.of(typeDescription), Duplication.SINGLE);
900                 }
901
902                 /**
903                  * {@inheritDoc}
904                  */

905                 public MethodDelegationBinder.MethodInvoker invoke() {
906                     return MethodDelegationBinder.MethodInvoker.Simple.INSTANCE;
907                 }
908
909                 /**
910                  * {@inheritDoc}
911                  */

912                 public List<MethodDelegationBinder.Record> getRecords() {
913                     return records;
914                 }
915             }
916         }
917
918         /**
919          * An implementation delegate for a static method delegation.
920          */

921         @HashCodeAndEqualsPlugin.Enhance
922         class ForStaticMethod implements ImplementationDelegate {
923
924             /**
925              * The precompiled records.
926              */

927             private final List<MethodDelegationBinder.Record> records;
928
929             /**
930              * Creates a new implementation delegate for a static method delegation.
931              *
932              * @param records The precompiled record.
933              */

934             protected ForStaticMethod(List<MethodDelegationBinder.Record> records) {
935                 this.records = records;
936             }
937
938             /**
939              * Precompiles a static method delegation for a given list of methods.
940              *
941              * @param methods                The methods to consider.
942              * @param methodDelegationBinder The method delegation binder to use.
943              * @return An appropriate implementation delegate.
944              */

945             protected static ImplementationDelegate of(MethodList<?> methods, MethodDelegationBinder methodDelegationBinder) {
946                 List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(methods.size());
947                 for (MethodDescription methodDescription : methods) {
948                     records.add(methodDelegationBinder.compile(methodDescription));
949                 }
950                 return new ForStaticMethod(records);
951             }
952
953             /**
954              * {@inheritDoc}
955              */

956             public InstrumentedType prepare(InstrumentedType instrumentedType) {
957                 return instrumentedType;
958             }
959
960             /**
961              * {@inheritDoc}
962              */

963             public ImplementationDelegate.Compiled compile(TypeDescription instrumentedType) {
964                 return new Compiled.ForStaticCall(records);
965             }
966         }
967
968         /**
969          * An implementation delegate for invoking methods on a field that is declared by the instrumented type or a super type.
970          */

971         @HashCodeAndEqualsPlugin.Enhance
972         abstract class ForField implements ImplementationDelegate {
973
974             /**
975              * The name of the field that is target of the delegation.
976              */

977             protected final String fieldName;
978
979             /**
980              * The method graph compiler to use.
981              */

982             protected final MethodGraph.Compiler methodGraphCompiler;
983
984             /**
985              * The parameter binders to use.
986              */

987             protected final List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
988
989             /**
990              * The matcher to use for filtering methods.
991              */

992             protected final ElementMatcher<? super MethodDescription> matcher;
993
994             /**
995              * Creates a new implementation delegate for a field delegation.
996              *
997              * @param fieldName           The name of the field that is target of the delegation.
998              * @param methodGraphCompiler The method graph compiler to use.
999              * @param parameterBinders    The parameter binders to use.
1000              * @param matcher             The matcher to use for filtering methods.
1001              */

1002             protected ForField(String fieldName,
1003                                MethodGraph.Compiler methodGraphCompiler,
1004                                List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1005                                ElementMatcher<? super MethodDescription> matcher) {
1006                 this.fieldName = fieldName;
1007                 this.methodGraphCompiler = methodGraphCompiler;
1008                 this.parameterBinders = parameterBinders;
1009                 this.matcher = matcher;
1010             }
1011
1012             /**
1013              * {@inheritDoc}
1014              */

1015             public Compiled compile(TypeDescription instrumentedType) {
1016                 FieldDescription fieldDescription = resolve(instrumentedType);
1017                 if (!fieldDescription.getType().asErasure().isVisibleTo(instrumentedType)) {
1018                     throw new IllegalStateException(fieldDescription + " is not visible to " + instrumentedType);
1019                 } else {
1020                     MethodList<?> candidates = methodGraphCompiler.compile(fieldDescription.getType(), instrumentedType)
1021                             .listNodes()
1022                             .asMethodList()
1023                             .filter(matcher);
1024                     List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(candidates.size());
1025                     MethodDelegationBinder methodDelegationBinder = TargetMethodAnnotationDrivenBinder.of(parameterBinders);
1026                     for (MethodDescription candidate : candidates) {
1027                         records.add(methodDelegationBinder.compile(candidate));
1028                     }
1029                     return new Compiled.ForField(fieldDescription, records);
1030                 }
1031             }
1032
1033             /**
1034              * Resolves the field to which is delegated.
1035              *
1036              * @param instrumentedType The instrumented type.
1037              * @return The field that is the delegation target.
1038              */

1039             protected abstract FieldDescription resolve(TypeDescription instrumentedType);
1040
1041             /**
1042              * An implementation target for a static field that is declared by the instrumented type and that is assigned an instance.
1043              */

1044             @HashCodeAndEqualsPlugin.Enhance
1045             protected static class WithInstance extends ForField {
1046
1047                 /**
1048                  * The target instance.
1049                  */

1050                 private final Object target;
1051
1052                 /**
1053                  * The field's type.
1054                  */

1055                 private final TypeDescription.Generic fieldType;
1056
1057                 /**
1058                  * Creates a new implementation delegate for invoking methods on a supplied instance.
1059                  *
1060                  * @param fieldName           The name of the field that is target of the delegation.
1061                  * @param methodGraphCompiler The method graph compiler to use.
1062                  * @param parameterBinders    The parameter binders to use.
1063                  * @param matcher             The matcher to use for filtering methods.
1064                  * @param target              The target instance.
1065                  * @param fieldType           The field's type.
1066                  */

1067                 protected WithInstance(String fieldName,
1068                                        MethodGraph.Compiler methodGraphCompiler,
1069                                        List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1070                                        ElementMatcher<? super MethodDescription> matcher,
1071                                        Object target,
1072                                        TypeDescription.Generic fieldType) {
1073                     super(fieldName, methodGraphCompiler, parameterBinders, matcher);
1074                     this.target = target;
1075                     this.fieldType = fieldType;
1076                 }
1077
1078                 /**
1079                  * {@inheritDoc}
1080                  */

1081                 public InstrumentedType prepare(InstrumentedType instrumentedType) {
1082                     return instrumentedType
1083                             .withField(new FieldDescription.Token(fieldName,
1084                                     Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_VOLATILE | Opcodes.ACC_SYNTHETIC,
1085                                     fieldType))
1086                             .withInitializer(new LoadedTypeInitializer.ForStaticField(fieldName, target));
1087                 }
1088
1089                 @Override
1090                 protected FieldDescription resolve(TypeDescription instrumentedType) {
1091                     if (!fieldType.asErasure().isVisibleTo(instrumentedType)) {
1092                         throw new IllegalStateException(fieldType + " is not visible to " + instrumentedType);
1093                     } else {
1094                         return instrumentedType.getDeclaredFields()
1095                                 .filter(named(fieldName).and(fieldType(fieldType.asErasure())))
1096                                 .getOnly();
1097                     }
1098                 }
1099             }
1100
1101             /**
1102              * An implementation target for a field that is declared by the instrumented type or a super type.
1103              */

1104             @HashCodeAndEqualsPlugin.Enhance
1105             protected static class WithLookup extends ForField {
1106
1107                 /**
1108                  * The field locator factory to use for locating the field to delegate to.
1109                  */

1110                 private final FieldLocator.Factory fieldLocatorFactory;
1111
1112                 /**
1113                  * Creates a new implementation delegate for a field that is declared by the instrumented type or any super type.
1114                  *
1115                  * @param fieldName           The name of the field that is target of the delegation.
1116                  * @param methodGraphCompiler The method graph compiler to use.
1117                  * @param parameterBinders    The parameter binders to use.
1118                  * @param matcher             The matcher to use for filtering methods.
1119                  * @param fieldLocatorFactory The field locator factory to use for locating the field to delegate to.
1120                  */

1121                 protected WithLookup(String fieldName,
1122                                      MethodGraph.Compiler methodGraphCompiler,
1123                                      List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1124                                      ElementMatcher<? super MethodDescription> matcher,
1125                                      FieldLocator.Factory fieldLocatorFactory) {
1126                     super(fieldName, methodGraphCompiler, parameterBinders, matcher);
1127                     this.fieldLocatorFactory = fieldLocatorFactory;
1128                 }
1129
1130                 /**
1131                  * {@inheritDoc}
1132                  */

1133                 public InstrumentedType prepare(InstrumentedType instrumentedType) {
1134                     return instrumentedType;
1135                 }
1136
1137                 @Override
1138                 protected FieldDescription resolve(TypeDescription instrumentedType) {
1139                     FieldLocator.Resolution resolution = fieldLocatorFactory.make(instrumentedType).locate(fieldName);
1140                     if (!resolution.isResolved()) {
1141                         throw new IllegalStateException("Could not locate " + fieldName + " on " + instrumentedType);
1142                     } else {
1143                         return resolution.getField();
1144                     }
1145                 }
1146             }
1147         }
1148
1149         /**
1150          * An implementation delegate for invoking a delegation target on the another methods return value.
1151          */

1152         @HashCodeAndEqualsPlugin.Enhance
1153         class ForMethodReturn implements ImplementationDelegate {
1154
1155             /**
1156              * The name of the method to invoke.
1157              */

1158             private final String name;
1159
1160             /**
1161              * The method graph compiler to use.
1162              */

1163             private final MethodGraph.Compiler methodGraphCompiler;
1164
1165             /**
1166              * The parameter binders to use.
1167              */

1168             private final List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
1169
1170             /**
1171              * The matcher to use for filtering methods.
1172              */

1173             private final ElementMatcher<? super MethodDescription> matcher;
1174
1175             /**
1176              * Creates a new implementation delegate for a method return value delegation.
1177              *
1178              * @param name                The name of the method to invoke.
1179              * @param methodGraphCompiler The method graph compiler to use.
1180              * @param parameterBinders    The parameter binders to use.
1181              * @param matcher             The matcher to use for filtering methods.
1182              */

1183             protected ForMethodReturn(String name,
1184                                       MethodGraph.Compiler methodGraphCompiler,
1185                                       List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1186                                       ElementMatcher<? super MethodDescription> matcher) {
1187                 this.name = name;
1188                 this.methodGraphCompiler = methodGraphCompiler;
1189                 this.parameterBinders = parameterBinders;
1190                 this.matcher = matcher;
1191             }
1192
1193             /**
1194              * {@inheritDoc}
1195              */

1196             public Compiled compile(TypeDescription instrumentedType) {
1197                 MethodList<?> targets = new MethodList.Explicit<MethodDescription>(CompoundList.<MethodDescription>of(
1198                         instrumentedType.getDeclaredMethods().filter(isStatic().or(isPrivate())),
1199                         methodGraphCompiler.compile(instrumentedType).listNodes().asMethodList())
1200                 ).filter(named(name).and(takesArguments(0)).and(not(returns(isPrimitive().or(isArray())))));
1201                 if (targets.size() != 1) {
1202                     throw new IllegalStateException(instrumentedType + " does not define method without arguments with name " + name + ": " + targets);
1203                 } else if (!targets.getOnly().getReturnType().asErasure().isVisibleTo(instrumentedType)) {
1204                     throw new IllegalStateException(targets.getOnly() + " is not visible to " + instrumentedType);
1205                 } else {
1206                     MethodList<?> candidates = methodGraphCompiler.compile(targets.getOnly().getReturnType(), instrumentedType)
1207                             .listNodes()
1208                             .asMethodList()
1209                             .filter(matcher);
1210                     List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(candidates.size());
1211                     MethodDelegationBinder methodDelegationBinder = TargetMethodAnnotationDrivenBinder.of(parameterBinders);
1212                     for (MethodDescription candidate : candidates) {
1213                         records.add(methodDelegationBinder.compile(candidate));
1214                     }
1215                     return new Compiled.ForMethodReturn(targets.get(0), records);
1216                 }
1217             }
1218
1219             /**
1220              * {@inheritDoc}
1221              */

1222             public InstrumentedType prepare(InstrumentedType instrumentedType) {
1223                 return instrumentedType;
1224             }
1225         }
1226
1227         /**
1228          * An implementation delegate for constructing an instance.
1229          */

1230         @HashCodeAndEqualsPlugin.Enhance
1231         class ForConstruction implements ImplementationDelegate {
1232
1233             /**
1234              * The type being constructed.
1235              */

1236             private final TypeDescription typeDescription;
1237
1238             /**
1239              * The precompiled delegation records.
1240              */

1241             private final List<MethodDelegationBinder.Record> records;
1242
1243             /**
1244              * Creates an implementation delegate for constructing a new instance.
1245              *
1246              * @param typeDescription The type being constructed.
1247              * @param records         The precompiled delegation records.
1248              */

1249             protected ForConstruction(TypeDescription typeDescription, List<MethodDelegationBinder.Record> records) {
1250                 this.typeDescription = typeDescription;
1251                 this.records = records;
1252             }
1253
1254             /**
1255              * Creates an implementation delegate for constructing a new instance.
1256              *
1257              * @param typeDescription        The type being constructed.
1258              * @param methods                The constructors to consider.
1259              * @param methodDelegationBinder The method delegation binder to use.
1260              * @return An appropriate implementation delegate.
1261              */

1262             protected static ImplementationDelegate of(TypeDescription typeDescription,
1263                                                        MethodList<?> methods,
1264                                                        MethodDelegationBinder methodDelegationBinder) {
1265                 List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(methods.size());
1266                 for (MethodDescription methodDescription : methods) {
1267                     records.add(methodDelegationBinder.compile(methodDescription));
1268                 }
1269                 return new ForConstruction(typeDescription, records);
1270             }
1271
1272             /**
1273              * {@inheritDoc}
1274              */

1275             public InstrumentedType prepare(InstrumentedType instrumentedType) {
1276                 return instrumentedType;
1277             }
1278
1279             /**
1280              * {@inheritDoc}
1281              */

1282             public Compiled compile(TypeDescription instrumentedType) {
1283                 return new Compiled.ForConstruction(typeDescription, records);
1284             }
1285         }
1286     }
1287
1288     /**
1289      * The appender for implementing a {@link net.bytebuddy.implementation.MethodDelegation}.
1290      */

1291     @HashCodeAndEqualsPlugin.Enhance
1292     protected static class Appender implements ByteCodeAppender {
1293
1294         /**
1295          * The implementation target of this implementation.
1296          */

1297         private final Target implementationTarget;
1298
1299         /**
1300          * The method delegation binder processor which is responsible for implementing the method delegation.
1301          */

1302         private final MethodDelegationBinder.Record processor;
1303
1304         /**
1305          * A termination handler for a method delegation binder.
1306          */

1307         private final MethodDelegationBinder.TerminationHandler terminationHandler;
1308
1309         /**
1310          * The assigner to use.
1311          */

1312         private final Assigner assigner;
1313
1314         /**
1315          * The compiled implementation delegate.
1316          */

1317         private final ImplementationDelegate.Compiled compiled;
1318
1319         /**
1320          * Creates a new appender for a method delegation.
1321          *
1322          * @param implementationTarget The implementation target of this implementation.
1323          * @param processor            The method delegation binder processor which is responsible for implementing the method delegation.
1324          * @param terminationHandler   A termination handler for a method delegation binder.
1325          * @param assigner             The assigner to use.
1326          * @param compiled             The compiled implementation delegate.
1327          */

1328         protected Appender(Target implementationTarget,
1329                            MethodDelegationBinder.Record processor,
1330                            MethodDelegationBinder.TerminationHandler terminationHandler,
1331                            Assigner assigner,
1332                            ImplementationDelegate.Compiled compiled) {
1333             this.implementationTarget = implementationTarget;
1334             this.processor = processor;
1335             this.terminationHandler = terminationHandler;
1336             this.assigner = assigner;
1337             this.compiled = compiled;
1338         }
1339
1340         /**
1341          * {@inheritDoc}
1342          */

1343         public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1344             StackManipulation.Size stackSize = new StackManipulation.Compound(
1345                     compiled.prepare(instrumentedMethod),
1346                     processor.bind(implementationTarget, instrumentedMethod, terminationHandler, compiled.invoke(), assigner)
1347             ).apply(methodVisitor, implementationContext);
1348             return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
1349         }
1350     }
1351
1352     /**
1353      * A {@link MethodDelegation} with custom configuration.
1354      */

1355     @HashCodeAndEqualsPlugin.Enhance
1356     public static class WithCustomProperties {
1357
1358         /**
1359          * The ambiguity resolver to use.
1360          */

1361         private final MethodDelegationBinder.AmbiguityResolver ambiguityResolver;
1362
1363         /**
1364          * The parameter binders to use.
1365          */

1366         private final List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
1367
1368         /**
1369          * The binding resolver being used to select the relevant method binding.
1370          */

1371         private final MethodDelegationBinder.BindingResolver bindingResolver;
1372
1373         /**
1374          * The matcher to use for filtering relevant methods.
1375          */

1376         private final ElementMatcher<? super MethodDescription> matcher;
1377
1378         /**
1379          * Creates a new method delegation with custom properties that does not filter any methods.
1380          *
1381          * @param ambiguityResolver The ambiguity resolver to use.
1382          * @param parameterBinders  The parameter binders to use.
1383          */

1384         protected WithCustomProperties(MethodDelegationBinder.AmbiguityResolver ambiguityResolver,
1385                                        List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders) {
1386             this(ambiguityResolver, parameterBinders, MethodDelegationBinder.BindingResolver.Default.INSTANCE, any());
1387         }
1388
1389         /**
1390          * Creates a new method delegation with custom properties.
1391          *
1392          * @param ambiguityResolver The ambiguity resolver to use.
1393          * @param parameterBinders  The parameter binders to use.
1394          * @param bindingResolver   The binding resolver being used to select the relevant method binding.
1395          * @param matcher           The matcher to use for filtering relevant methods.
1396          */

1397         private WithCustomProperties(MethodDelegationBinder.AmbiguityResolver ambiguityResolver,
1398                                      List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1399                                      MethodDelegationBinder.BindingResolver bindingResolver,
1400                                      ElementMatcher<? super MethodDescription> matcher) {
1401             this.ambiguityResolver = ambiguityResolver;
1402             this.parameterBinders = parameterBinders;
1403             this.bindingResolver = bindingResolver;
1404             this.matcher = matcher;
1405         }
1406
1407         /**
1408          * Configures this method delegation to use the supplied ambiguity resolvers when deciding which out of two ore
1409          * more legal delegation targets should be considered.
1410          *
1411          * @param ambiguityResolver The ambiguity resolvers to use in their application order.
1412          * @return A new delegation configuration which also applies the supplied ambiguity resolvers.
1413          */

1414         public WithCustomProperties withResolvers(MethodDelegationBinder.AmbiguityResolver... ambiguityResolver) {
1415             return withResolvers(Arrays.asList(ambiguityResolver));
1416         }
1417
1418         /**
1419          * Configures this method delegation to use the supplied ambiguity resolvers when deciding which out of two ore
1420          * more legal delegation targets should be considered.
1421          *
1422          * @param ambiguityResolvers The ambiguity resolvers to use in their application order.
1423          * @return A new delegation configuration which also applies the supplied ambiguity resolvers.
1424          */

1425         public WithCustomProperties withResolvers(List<? extends MethodDelegationBinder.AmbiguityResolver> ambiguityResolvers) {
1426             return new WithCustomProperties(new MethodDelegationBinder.AmbiguityResolver.Compound(CompoundList.of(this.ambiguityResolver,
1427                     ambiguityResolvers)), parameterBinders, bindingResolver, matcher);
1428         }
1429
1430         /**
1431          * Configures this method delegation to use the supplied parameter binders when deciding what value to assign to
1432          * a parameter of a delegation target.
1433          *
1434          * @param parameterBinder The parameter binders to use.
1435          * @return A new delegation configuration which also applies the supplied parameter binders.
1436          */

1437         public WithCustomProperties withBinders(TargetMethodAnnotationDrivenBinder.ParameterBinder<?>... parameterBinder) {
1438             return withBinders(Arrays.asList(parameterBinder));
1439         }
1440
1441         /**
1442          * Configures this method delegation to use the supplied parameter binders when deciding what value to assign to
1443          * a parameter of a delegation target.
1444          *
1445          * @param parameterBinders The parameter binders to use.
1446          * @return A new delegation configuration which also applies the supplied parameter binders.
1447          */

1448         public WithCustomProperties withBinders(List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders) {
1449             return new WithCustomProperties(ambiguityResolver, CompoundList.of(this.parameterBinders, parameterBinders), bindingResolver, matcher);
1450         }
1451
1452         /**
1453          * Configures a custom binding resolver which is responsible for choosing a method binding among multiple candidates. Configuring
1454          * a resolver overrides any previous configuration.
1455          *
1456          * @param bindingResolver The binding resolver being used to select the relevant method binding.
1457          * @return A new delegation configuration which applies the supplied binding resolver.
1458          */

1459         public WithCustomProperties withBindingResolver(MethodDelegationBinder.BindingResolver bindingResolver) {
1460             return new WithCustomProperties(ambiguityResolver, parameterBinders, bindingResolver, matcher);
1461         }
1462
1463         /**
1464          * Configures this method delegation to only consider methods or constructors as a delegation target if they match the supplied matcher.
1465          *
1466          * @param matcher The matcher any delegation target needs to match in order to be considered a for delegation.
1467          * @return A new delegation configuration which only considers methods for delegation if they match the supplied matcher.
1468          */

1469         public WithCustomProperties filter(ElementMatcher<? super MethodDescription> matcher) {
1470             return new WithCustomProperties(ambiguityResolver,
1471                     parameterBinders,
1472                     bindingResolver,
1473                     new ElementMatcher.Junction.Conjunction<MethodDescription>(this.matcher, matcher));
1474         }
1475
1476         /**
1477          * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered
1478          * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if
1479          * the target type is either public or in the same package as the instrumented type and if the target method is either public
1480          * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if
1481          * the interception is targeting the instrumented type.
1482          *
1483          * @param type The target type for the delegation.
1484          * @return A method delegation that redirects method calls to a static method of the supplied type.
1485          */

1486         public MethodDelegation to(Class<?> type) {
1487             return to(TypeDescription.ForLoadedType.of(type));
1488         }
1489
1490         /**
1491          * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered
1492          * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if
1493          * the target type is either public or in the same package as the instrumented type and if the target method is either public
1494          * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if
1495          * the delegation is targeting the instrumented type.
1496          *
1497          * @param typeDescription The target type for the delegation.
1498          * @return A method delegation that redirects method calls to a static method of the supplied type.
1499          */

1500         public MethodDelegation to(TypeDescription typeDescription) {
1501             if (typeDescription.isArray()) {
1502                 throw new IllegalArgumentException("Cannot delegate to array " + typeDescription);
1503             } else if (typeDescription.isPrimitive()) {
1504                 throw new IllegalArgumentException("Cannot delegate to primitive " + typeDescription);
1505             }
1506             return new MethodDelegation(ImplementationDelegate.ForStaticMethod.of(typeDescription.getDeclaredMethods().filter(isStatic().and(matcher)),
1507                     TargetMethodAnnotationDrivenBinder.of(parameterBinders)), parameterBinders, ambiguityResolver, bindingResolver);
1508         }
1509
1510         /**
1511          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1512          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1513          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1514          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1515          * a delegation target if the delegation is targeting the instrumented type.
1516          *
1517          * @param target The target instance for the delegation.
1518          * @return A method delegation that redirects method calls to a static method of the supplied type.
1519          */

1520         public MethodDelegation to(Object target) {
1521             return to(target, MethodGraph.Compiler.DEFAULT);
1522         }
1523
1524         /**
1525          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1526          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1527          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1528          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1529          * a delegation target if the delegation is targeting the instrumented type.
1530          *
1531          * @param target              The target instance for the delegation.
1532          * @param methodGraphCompiler The method graph compiler to use.
1533          * @return A method delegation that redirects method calls to a static method of the supplied type.
1534          */

1535         public MethodDelegation to(Object target, MethodGraph.Compiler methodGraphCompiler) {
1536             return to(target, target.getClass(), methodGraphCompiler);
1537         }
1538
1539         /**
1540          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1541          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1542          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1543          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1544          * a delegation target if the delegation is targeting the instrumented type.
1545          *
1546          * @param target    The target instance for the delegation.
1547          * @param fieldName The name of the field that is holding the {@code target} instance.
1548          * @return A method delegation that redirects method calls to a static method of the supplied type.
1549          */

1550         public MethodDelegation to(Object target, String fieldName) {
1551             return to(target, fieldName, MethodGraph.Compiler.DEFAULT);
1552         }
1553
1554         /**
1555          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1556          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1557          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1558          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1559          * a delegation target if the delegation is targeting the instrumented type.
1560          *
1561          * @param target              The target instance for the delegation.
1562          * @param fieldName           The name of the field that is holding the {@code target} instance.
1563          * @param methodGraphCompiler The method graph compiler to use.
1564          * @return A method delegation that redirects method calls to a static method of the supplied type.
1565          */

1566         public MethodDelegation to(Object target, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
1567             return to(target, target.getClass(), fieldName, methodGraphCompiler);
1568         }
1569
1570         /**
1571          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1572          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1573          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1574          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1575          * a delegation target if the delegation is targeting the instrumented type.
1576          *
1577          * @param target The target instance for the delegation.
1578          * @param type   The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1579          * @return A method delegation that redirects method calls to a static method of the supplied type.
1580          */

1581         public MethodDelegation to(Object target, Type type) {
1582             return to(target, type, MethodGraph.Compiler.DEFAULT);
1583         }
1584
1585         /**
1586          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1587          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1588          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1589          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1590          * a delegation target if the delegation is targeting the instrumented type.
1591          *
1592          * @param target              The target instance for the delegation.
1593          * @param type                The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1594          * @param methodGraphCompiler The method graph compiler to use.
1595          * @return A method delegation that redirects method calls to a static method of the supplied type.
1596          */

1597         public MethodDelegation to(Object target, Type type, MethodGraph.Compiler methodGraphCompiler) {
1598             return to(target,
1599                     type,
1600                     ImplementationDelegate.FIELD_NAME_PREFIX + "$" + RandomString.hashOf(target.hashCode()),
1601                     methodGraphCompiler);
1602         }
1603
1604         /**
1605          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1606          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1607          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1608          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1609          * a delegation target if the delegation is targeting the instrumented type.
1610          *
1611          * @param target    The target instance for the delegation.
1612          * @param type      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1613          * @param fieldName The name of the field that is holding the {@code target} instance.
1614          * @return A method delegation that redirects method calls to a static method of the supplied type.
1615          */

1616         public MethodDelegation to(Object target, Type type, String fieldName) {
1617             return to(target, type, fieldName, MethodGraph.Compiler.DEFAULT);
1618         }
1619
1620         /**
1621          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1622          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1623          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1624          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1625          * a delegation target if the delegation is targeting the instrumented type.
1626          *
1627          * @param target              The target instance for the delegation.
1628          * @param type                The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1629          * @param fieldName           The name of the field that is holding the {@code target} instance.
1630          * @param methodGraphCompiler The method graph compiler to use.
1631          * @return A method delegation that redirects method calls to a static method of the supplied type.
1632          */

1633         public MethodDelegation to(Object target, Type type, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
1634             return to(target, TypeDefinition.Sort.describe(type), fieldName, methodGraphCompiler);
1635         }
1636
1637         /**
1638          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1639          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1640          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1641          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1642          * a delegation target if the delegation is targeting the instrumented type.
1643          *
1644          * @param target         The target instance for the delegation.
1645          * @param typeDefinition The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1646          * @return A method delegation that redirects method calls to a static method of the supplied type.
1647          */

1648         public MethodDelegation to(Object target, TypeDefinition typeDefinition) {
1649             return to(target, typeDefinition, MethodGraph.Compiler.DEFAULT);
1650         }
1651
1652         /**
1653          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1654          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1655          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1656          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1657          * a delegation target if the delegation is targeting the instrumented type.
1658          *
1659          * @param target              The target instance for the delegation.
1660          * @param typeDefinition      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1661          * @param methodGraphCompiler The method graph compiler to use.
1662          * @return A method delegation that redirects method calls to a static method of the supplied type.
1663          */

1664         public MethodDelegation to(Object target, TypeDefinition typeDefinition, MethodGraph.Compiler methodGraphCompiler) {
1665             return to(target,
1666                     typeDefinition,
1667                     ImplementationDelegate.FIELD_NAME_PREFIX + "$" + RandomString.hashOf(target.hashCode()),
1668                     methodGraphCompiler);
1669         }
1670
1671         /**
1672          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1673          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1674          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1675          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1676          * a delegation target if the delegation is targeting the instrumented type.
1677          *
1678          * @param target         The target instance for the delegation.
1679          * @param typeDefinition The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1680          * @param fieldName      The name of the field that is holding the {@code target} instance.
1681          * @return A method delegation that redirects method calls to a static method of the supplied type.
1682          */

1683         public MethodDelegation to(Object target, TypeDefinition typeDefinition, String fieldName) {
1684             return to(target, typeDefinition, fieldName, MethodGraph.Compiler.DEFAULT);
1685         }
1686
1687         /**
1688          * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1689          * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1690          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1691          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1692          * a delegation target if the delegation is targeting the instrumented type.
1693          *
1694          * @param target              The target instance for the delegation.
1695          * @param typeDefinition      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1696          * @param fieldName           The name of the field that is holding the {@code target} instance.
1697          * @param methodGraphCompiler The method graph compiler to use.
1698          * @return A method delegation that redirects method calls to a static method of the supplied type.
1699          */

1700         public MethodDelegation to(Object target, TypeDefinition typeDefinition, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
1701             if (!typeDefinition.asErasure().isInstance(target)) {
1702                 throw new IllegalArgumentException(target + " is not an instance of " + typeDefinition);
1703             }
1704             return new MethodDelegation(new ImplementationDelegate.ForField.WithInstance(fieldName,
1705                     methodGraphCompiler,
1706                     parameterBinders,
1707                     matcher,
1708                     target,
1709                     typeDefinition.asGenericType()), parameterBinders, ambiguityResolver, bindingResolver);
1710         }
1711
1712         /**
1713          * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target,
1714          * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is
1715          * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in
1716          * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is
1717          * targeting the instrumented type.
1718          *
1719          * @param type The type to construct.
1720          * @return A delegation that redirects method calls to a constructor of the supplied type.
1721          */

1722         public MethodDelegation toConstructor(Class<?> type) {
1723             return toConstructor(TypeDescription.ForLoadedType.of(type));
1724         }
1725
1726         /**
1727          * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target,
1728          * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is
1729          * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in
1730          * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is
1731          * targeting the instrumented type.
1732          *
1733          * @param typeDescription The type to construct.
1734          * @return A delegation that redirects method calls to a constructor of the supplied type.
1735          */

1736         public MethodDelegation toConstructor(TypeDescription typeDescription) {
1737             return new MethodDelegation(ImplementationDelegate.ForConstruction.of(typeDescription,
1738                     typeDescription.getDeclaredMethods().filter(isConstructor().and(matcher)),
1739                     TargetMethodAnnotationDrivenBinder.of(parameterBinders)), parameterBinders, ambiguityResolver, bindingResolver);
1740         }
1741
1742         /**
1743          * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
1744          * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
1745          * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1746          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1747          * a delegation target if the delegation is targeting the instrumented type.
1748          *
1749          * @param name The field's name.
1750          * @return A delegation that redirects invocations to a method of the specified field's instance.
1751          */

1752         public MethodDelegation toField(String name) {
1753             return toField(name, FieldLocator.ForClassHierarchy.Factory.INSTANCE);
1754         }
1755
1756         /**
1757          * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
1758          * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
1759          * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1760          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1761          * a delegation target if the delegation is targeting the instrumented type.
1762          *
1763          * @param name                The field's name.
1764          * @param fieldLocatorFactory The field locator factory to use.
1765          * @return A delegation that redirects invocations to a method of the specified field's instance.
1766          */

1767         public MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory) {
1768             return toField(name, fieldLocatorFactory, MethodGraph.Compiler.DEFAULT);
1769         }
1770
1771         /**
1772          * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
1773          * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
1774          * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1775          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1776          * a delegation target if the delegation is targeting the instrumented type.
1777          *
1778          * @param name                The field's name.
1779          * @param methodGraphCompiler The method graph compiler to use.
1780          * @return A delegation that redirects invocations to a method of the specified field's instance.
1781          */

1782         public MethodDelegation toField(String name, MethodGraph.Compiler methodGraphCompiler) {
1783             return toField(name, FieldLocator.ForClassHierarchy.Factory.INSTANCE, methodGraphCompiler);
1784         }
1785
1786         /**
1787          * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
1788          * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
1789          * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1790          * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1791          * a delegation target if the delegation is targeting the instrumented type.
1792          *
1793          * @param name                The field's name.
1794          * @param fieldLocatorFactory The field locator factory to use.
1795          * @param methodGraphCompiler The method graph compiler to use.
1796          * @return A delegation that redirects invocations to a method of the specified field's instance.
1797          */

1798         public MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory, MethodGraph.Compiler methodGraphCompiler) {
1799             return new MethodDelegation(new ImplementationDelegate.ForField.WithLookup(name,
1800                     methodGraphCompiler,
1801                     parameterBinders,
1802                     matcher,
1803                     fieldLocatorFactory), parameterBinders, ambiguityResolver, bindingResolver);
1804         }
1805
1806         /**
1807          * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the
1808          * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1809          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if
1810          * the method is either public or non-private and in the same package as the instrumented type. Private methods can only
1811          * be used as a delegation target if the delegation is targeting the instrumented type.
1812          *
1813          * @param name The name of the method that returns the delegation target.
1814          * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
1815          */

1816         public MethodDelegation toMethodReturnOf(String name) {
1817             return toMethodReturnOf(name, MethodGraph.Compiler.DEFAULT);
1818         }
1819
1820         /**
1821          * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the
1822          * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1823          * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if
1824          * the method is either public or non-private and in the same package as the instrumented type. Private methods can only
1825          * be used as a delegation target if the delegation is targeting the instrumented type.
1826          *
1827          * @param name                The name of the method that returns the delegation target.
1828          * @param methodGraphCompiler The method graph compiler to use.
1829          * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
1830          */

1831         public MethodDelegation toMethodReturnOf(String name, MethodGraph.Compiler methodGraphCompiler) {
1832             return new MethodDelegation(new ImplementationDelegate.ForMethodReturn(name,
1833                     methodGraphCompiler,
1834                     parameterBinders,
1835                     matcher), parameterBinders, ambiguityResolver, bindingResolver);
1836         }
1837     }
1838 }
1839