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> </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 null} for 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> </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> </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> </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