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.ClassFileVersion;
19 import net.bytebuddy.build.CachedReturnPlugin;
20 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
21 import net.bytebuddy.description.annotation.AnnotationList;
22 import net.bytebuddy.description.annotation.AnnotationValue;
23 import net.bytebuddy.description.field.FieldDescription;
24 import net.bytebuddy.description.method.MethodDescription;
25 import net.bytebuddy.description.method.ParameterDescription;
26 import net.bytebuddy.description.method.ParameterList;
27 import net.bytebuddy.description.modifier.Visibility;
28 import net.bytebuddy.description.type.TypeDefinition;
29 import net.bytebuddy.description.type.TypeDescription;
30 import net.bytebuddy.description.type.TypeList;
31 import net.bytebuddy.dynamic.DynamicType;
32 import net.bytebuddy.dynamic.scaffold.InstrumentedType;
33 import net.bytebuddy.dynamic.scaffold.MethodGraph;
34 import net.bytebuddy.dynamic.scaffold.TypeInitializer;
35 import net.bytebuddy.dynamic.scaffold.TypeWriter;
36 import net.bytebuddy.implementation.attribute.AnnotationValueFilter;
37 import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
38 import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
39 import net.bytebuddy.implementation.bytecode.StackManipulation;
40 import net.bytebuddy.implementation.bytecode.member.FieldAccess;
41 import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
42 import net.bytebuddy.implementation.bytecode.member.MethodReturn;
43 import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
44 import net.bytebuddy.utility.CompoundList;
45 import net.bytebuddy.utility.RandomString;
46 import net.bytebuddy.jar.asm.ClassVisitor;
47 import net.bytebuddy.jar.asm.FieldVisitor;
48 import net.bytebuddy.jar.asm.MethodVisitor;
49 import net.bytebuddy.jar.asm.Opcodes;
50
51 import java.util.*;
52
53 /**
54  * An implementation is responsible for implementing methods of a dynamically created type as byte code. An
55  * implementation is applied in two stages:
56  * <ol>
57  * <li>The implementation is able to prepare an instrumented type by adding fields and/or helper methods that are
58  * required for the methods implemented by this implementation. Furthermore,
59  * {@link LoadedTypeInitializer}s  and byte code for the type initializer can be registered for the instrumented
60  * type.</li>
61  * <li>Any implementation is required to supply a byte code appender that is responsible for providing the byte code
62  * to the instrumented methods that were delegated to this implementation. This byte code appender is also
63  * be responsible for providing implementations for the methods added in step <i>1</i>.</li>
64  * </ol>
65  * <p>&nbsp;</p>
66  * An implementation should provide meaningful implementations of both {@link java.lang.Object#equals(Object)}
67  * and {@link Object#hashCode()} if it wants to avoid to be used twice within the creation of a dynamic type. For two
68  * equal implementations only one will be applied on the creation of a dynamic type.
69  */

70 public interface Implementation extends InstrumentedType.Prepareable {
71
72     /**
73      * Creates a byte code appender that determines the implementation of the instrumented type's methods.
74      *
75      * @param implementationTarget The target of the current implementation.
76      * @return A byte code appender for implementing methods delegated to this implementation. This byte code appender
77      * is also responsible for handling methods that were added by this implementation on the call to
78      * {@link Implementation#prepare(InstrumentedType)}.
79      */

80     ByteCodeAppender appender(Target implementationTarget);
81
82     /**
83      * Represents an implementation that can be chained together with another implementation.
84      */

85     interface Composable extends Implementation {
86
87         /**
88          * Appends the supplied implementation to this implementation.
89          *
90          * @param implementation The subsequent implementation.
91          * @return An implementation that combines this implementation with the provided one.
92          */

93         Implementation andThen(Implementation implementation);
94
95         /**
96          * Appends the supplied composable implementation to this implementation.
97          *
98          * @param implementation The subsequent composable implementation.
99          * @return A composable implementation that combines this implementation with the provided one.
100          */

101         Composable andThen(Composable implementation);
102     }
103
104     /**
105      * Represents an type-specific method invocation on the current instrumented type which is not legal from outside
106      * the type such as a super method or default method invocation. Legal instances of special method invocations must
107      * be equal to one another if they represent the same invocation target.
108      */

109     interface SpecialMethodInvocation extends StackManipulation {
110
111         /**
112          * Returns the method that represents this special method invocation. This method can be different even for
113          * equal special method invocations, dependant on the method that was used to request such an invocation by the
114          * means of a {@link Implementation.Target}.
115          *
116          * @return The method description that describes this instances invocation target.
117          */

118         MethodDescription getMethodDescription();
119
120         /**
121          * Returns the target type the represented method is invoked on.
122          *
123          * @return The type the represented method is invoked on.
124          */

125         TypeDescription getTypeDescription();
126
127         /**
128          * Checks that this special method invocation is compatible with the supplied type representation.
129          *
130          * @param token The type token to check against.
131          * @return This special method invocation or an illegal invocation if the method invocation is not applicable.
132          */

133         SpecialMethodInvocation withCheckedCompatibilityTo(MethodDescription.TypeToken token);
134
135         /**
136          * A canonical implementation of an illegal {@link Implementation.SpecialMethodInvocation}.
137          */

138         enum Illegal implements SpecialMethodInvocation {
139
140             /**
141              * The singleton instance.
142              */

143             INSTANCE;
144
145             /**
146              * {@inheritDoc}
147              */

148             public boolean isValid() {
149                 return false;
150             }
151
152             /**
153              * {@inheritDoc}
154              */

155             public Size apply(MethodVisitor methodVisitor, Context implementationContext) {
156                 throw new IllegalStateException("Cannot implement an undefined method");
157             }
158
159             /**
160              * {@inheritDoc}
161              */

162             public MethodDescription getMethodDescription() {
163                 throw new IllegalStateException("An illegal special method invocation must not be applied");
164             }
165
166             /**
167              * {@inheritDoc}
168              */

169             public TypeDescription getTypeDescription() {
170                 throw new IllegalStateException("An illegal special method invocation must not be applied");
171             }
172
173             /**
174              * {@inheritDoc}
175              */

176             public SpecialMethodInvocation withCheckedCompatibilityTo(MethodDescription.TypeToken token) {
177                 return this;
178             }
179         }
180
181         /**
182          * An abstract base implementation of a valid special method invocation.
183          */

184         abstract class AbstractBase implements SpecialMethodInvocation {
185
186             /**
187              * {@inheritDoc}
188              */

189             public boolean isValid() {
190                 return true;
191             }
192
193             @Override
194             @CachedReturnPlugin.Enhance
195             public int hashCode() {
196                 return 31 * getMethodDescription().asSignatureToken().hashCode() + getTypeDescription().hashCode();
197             }
198
199             @Override
200             public boolean equals(Object other) {
201                 if (this == other) {
202                     return true;
203                 } else if (!(other instanceof SpecialMethodInvocation)) {
204                     return false;
205                 }
206                 SpecialMethodInvocation specialMethodInvocation = (SpecialMethodInvocation) other;
207                 return getMethodDescription().asSignatureToken().equals(specialMethodInvocation.getMethodDescription().asSignatureToken())
208                         && getTypeDescription().equals(specialMethodInvocation.getTypeDescription());
209             }
210         }
211
212         /**
213          * A canonical implementation of a {@link SpecialMethodInvocation}.
214          */

215         class Simple extends SpecialMethodInvocation.AbstractBase {
216
217             /**
218              * The method description that is represented by this legal special method invocation.
219              */

220             private final MethodDescription methodDescription;
221
222             /**
223              * The type description that is represented by this legal special method invocation.
224              */

225             private final TypeDescription typeDescription;
226
227             /**
228              * A stack manipulation representing the method's invocation on the type description.
229              */

230             private final StackManipulation stackManipulation;
231
232             /**
233              * Creates a new legal special method invocation.
234              *
235              * @param methodDescription The method that represents the special method invocation.
236              * @param typeDescription   The type on which the method should be invoked on by an {@code INVOKESPECIAL}
237              *                          invocation.
238              * @param stackManipulation The stack manipulation that represents this special method invocation.
239              */

240             protected Simple(MethodDescription methodDescription, TypeDescription typeDescription, StackManipulation stackManipulation) {
241                 this.methodDescription = methodDescription;
242                 this.typeDescription = typeDescription;
243                 this.stackManipulation = stackManipulation;
244             }
245
246             /**
247              * Creates a special method invocation for a given invocation target.
248              *
249              * @param methodDescription The method that represents the special method invocation.
250              * @param typeDescription   The type on which the method should be invoked on by an {@code INVOKESPECIAL}
251              *                          invocation.
252              * @return A special method invocation representing a legal invocation if the method can be invoked
253              * specially on the target type or an illegal invocation if this is not possible.
254              */

255             public static SpecialMethodInvocation of(MethodDescription methodDescription, TypeDescription typeDescription) {
256                 StackManipulation stackManipulation = MethodInvocation.invoke(methodDescription).special(typeDescription);
257                 return stackManipulation.isValid()
258                         ? new Simple(methodDescription, typeDescription, stackManipulation)
259                         : SpecialMethodInvocation.Illegal.INSTANCE;
260             }
261
262             /**
263              * {@inheritDoc}
264              */

265             public MethodDescription getMethodDescription() {
266                 return methodDescription;
267             }
268
269             /**
270              * {@inheritDoc}
271              */

272             public TypeDescription getTypeDescription() {
273                 return typeDescription;
274             }
275
276             /**
277              * {@inheritDoc}
278              */

279             public Size apply(MethodVisitor methodVisitor, Context implementationContext) {
280                 return stackManipulation.apply(methodVisitor, implementationContext);
281             }
282
283             /**
284              * {@inheritDoc}
285              */

286             public SpecialMethodInvocation withCheckedCompatibilityTo(MethodDescription.TypeToken token) {
287                 if (methodDescription.asTypeToken().equals(token)) {
288                     return this;
289                 } else {
290                     return SpecialMethodInvocation.Illegal.INSTANCE;
291                 }
292             }
293         }
294     }
295
296     /**
297      * The target of an implementation. Implementation targets must be immutable and can be queried without altering
298      * the implementation result. An implementation target provides information on the type that is to be created
299      * where it is the implementation's responsibility to cache expensive computations, especially such computations
300      * that require reflective look-up.
301      */

302     interface Target {
303
304         /**
305          * Returns a description of the instrumented type.
306          *
307          * @return A description of the instrumented type.
308          */

309         TypeDescription getInstrumentedType();
310
311         /**
312          * Identifies the origin type of an implementation. The origin type describes the type that is subject to
313          * any form of enhancement. If a subclass of a given type is generated, the base type of this subclass
314          * describes the origin type. If a given type is redefined or rebased, the origin type is described by the
315          * instrumented type itself.
316          *
317          * @return The origin type of this implementation.
318          */

319         TypeDefinition getOriginType();
320
321         /**
322          * Creates a special method invocation for invoking the super method of the given method.
323          *
324          * @param token A token of the method that is to be invoked as a super method.
325          * @return The corresponding special method invocation which might be illegal if the requested invocation is not legal.
326          */

327         SpecialMethodInvocation invokeSuper(MethodDescription.SignatureToken token);
328
329         /**
330          * Creates a special method invocation for invoking a default method with the given token. The default method call must
331          * not be ambiguous or an illegal special method invocation is returned.
332          *
333          * @param token A token of the method that is to be invoked as a default method.
334          * @return The corresponding default method invocation which might be illegal if the requested invocation is not legal or ambiguous.
335          */

336         SpecialMethodInvocation invokeDefault(MethodDescription.SignatureToken token);
337
338         /**
339          * Creates a special method invocation for invoking a default method.
340          *
341          * @param targetType The interface on which the default method is to be invoked.
342          * @param token      A token that uniquely describes the method to invoke.
343          * @return The corresponding special method invocation which might be illegal if the requested invocation is
344          * not legal.
345          */

346         SpecialMethodInvocation invokeDefault(MethodDescription.SignatureToken token, TypeDescription targetType);
347
348         /**
349          * Invokes a dominant method, i.e. if the method token can be invoked as a super method invocation, this invocation is considered dominant.
350          * Alternatively, a method invocation is attempted on an interface type as a default method invocation only if this invocation is not ambiguous
351          * for several interfaces.
352          *
353          * @param token The method token representing the method to be invoked.
354          * @return A special method invocation for a method representing the method token.
355          */

356         SpecialMethodInvocation invokeDominant(MethodDescription.SignatureToken token);
357
358         /**
359          * A factory for creating an {@link Implementation.Target}.
360          */

361         interface Factory {
362
363             /**
364              * Creates an implementation target.
365              *
366              * @param instrumentedType The instrumented type.
367              * @param methodGraph      A method graph of the instrumented type.
368              * @param classFileVersion The type's class file version.
369              * @return An implementation target for the instrumented type.
370              */

371             Target make(TypeDescription instrumentedType, MethodGraph.Linked methodGraph, ClassFileVersion classFileVersion);
372         }
373
374         /**
375          * An abstract base implementation for an {@link Implementation.Target}.
376          */

377         @HashCodeAndEqualsPlugin.Enhance
378         abstract class AbstractBase implements Target {
379
380             /**
381              * The instrumented type.
382              */

383             protected final TypeDescription instrumentedType;
384
385             /**
386              * The instrumented type's method graph.
387              */

388             protected final MethodGraph.Linked methodGraph;
389
390             /**
391              * The default method invocation mode to apply.
392              */

393             protected final DefaultMethodInvocation defaultMethodInvocation;
394
395             /**
396              * Creates a new implementation target.
397              *
398              * @param instrumentedType        The instrumented type.
399              * @param methodGraph             The instrumented type's method graph.
400              * @param defaultMethodInvocation The default method invocation mode to apply.
401              */

402             protected AbstractBase(TypeDescription instrumentedType, MethodGraph.Linked methodGraph, DefaultMethodInvocation defaultMethodInvocation) {
403                 this.instrumentedType = instrumentedType;
404                 this.methodGraph = methodGraph;
405                 this.defaultMethodInvocation = defaultMethodInvocation;
406             }
407
408             /**
409              * {@inheritDoc}
410              */

411             public TypeDescription getInstrumentedType() {
412                 return instrumentedType;
413             }
414
415             /**
416              * {@inheritDoc}
417              */

418             public SpecialMethodInvocation invokeDefault(MethodDescription.SignatureToken token) {
419                 SpecialMethodInvocation specialMethodInvocation = SpecialMethodInvocation.Illegal.INSTANCE;
420                 for (TypeDescription interfaceType : instrumentedType.getInterfaces().asErasures()) {
421                     SpecialMethodInvocation invocation = invokeDefault(token, interfaceType).withCheckedCompatibilityTo(token.asTypeToken());
422                     if (invocation.isValid()) {
423                         if (specialMethodInvocation.isValid()) {
424                             return SpecialMethodInvocation.Illegal.INSTANCE;
425                         } else {
426                             specialMethodInvocation = invocation;
427                         }
428                     }
429                 }
430                 return specialMethodInvocation;
431             }
432
433             /**
434              * {@inheritDoc}
435              */

436             public SpecialMethodInvocation invokeDefault(MethodDescription.SignatureToken token, TypeDescription targetType) {
437                 return defaultMethodInvocation.apply(methodGraph.getInterfaceGraph(targetType).locate(token), targetType);
438             }
439
440             /**
441              * {@inheritDoc}
442              */

443             public SpecialMethodInvocation invokeDominant(MethodDescription.SignatureToken token) {
444                 SpecialMethodInvocation specialMethodInvocation = invokeSuper(token);
445                 return specialMethodInvocation.isValid()
446                         ? specialMethodInvocation
447                         : invokeDefault(token);
448             }
449
450             /**
451              * Determines if default method invocations are possible.
452              */

453             protected enum DefaultMethodInvocation {
454
455                 /**
456                  * Permits default method invocations, if an interface declaring a default method is possible.
457                  */

458                 ENABLED {
459                     @Override
460                     protected SpecialMethodInvocation apply(MethodGraph.Node node, TypeDescription targetType) {
461                         return node.getSort().isUnique()
462                                 ? SpecialMethodInvocation.Simple.of(node.getRepresentative(), targetType)
463                                 : SpecialMethodInvocation.Illegal.INSTANCE;
464                     }
465                 },
466
467                 /**
468                  * Does not permit default method invocations.
469                  */

470                 DISABLED {
471                     @Override
472                     protected SpecialMethodInvocation apply(MethodGraph.Node node, TypeDescription targetType) {
473                         return SpecialMethodInvocation.Illegal.INSTANCE;
474                     }
475                 };
476
477                 /**
478                  * Resolves a default method invocation depending on the class file version permitting such calls.
479                  *
480                  * @param classFileVersion The class file version to resolve for.
481                  * @return A suitable default method invocation mode.
482                  */

483                 public static DefaultMethodInvocation of(ClassFileVersion classFileVersion) {
484                     return classFileVersion.isAtLeast(ClassFileVersion.JAVA_V8)
485                             ? ENABLED
486                             : DISABLED;
487                 }
488
489                 /**
490                  * Resolves a default method invocation for a given node.
491                  *
492                  * @param node       The node representing the default method call.
493                  * @param targetType The target type defining the default method.
494                  * @return A suitable special method invocation.
495                  */

496                 protected abstract SpecialMethodInvocation apply(MethodGraph.Node node, TypeDescription targetType);
497             }
498         }
499     }
500
501     /**
502      * The context for an implementation application. An implementation context represents a mutable data structure
503      * where any registration is irrevocable. Calling methods on an implementation context should be considered equally
504      * sensitive as calling a {@link net.bytebuddy.jar.asm.MethodVisitor}. As such, an implementation context and a
505      * {@link net.bytebuddy.jar.asm.MethodVisitor} are complementary for creating an new Java type.
506      */

507     interface Context extends MethodAccessorFactory {
508
509         /**
510          * Registers an auxiliary type as required for the current implementation. Registering a type will cause the
511          * creation of this type even if this type is not effectively used for the current implementation.
512          *
513          * @param auxiliaryType The auxiliary type that is required for the current implementation.
514          * @return A description of the registered auxiliary type.
515          */

516         TypeDescription register(AuxiliaryType auxiliaryType);
517
518         /**
519          * Caches a single value by storing it in form of a {@code private}, {@code final} and {@code static} field.
520          * By caching values, expensive instance creations can be avoided and object identity can be preserved.
521          * The field is initiated in a generated class's static initializer.
522          *
523          * @param fieldValue A stack manipulation for creating the value that is to be cached in a {@code static} field.
524          *                   After executing the stack manipulation, exactly one value must be put onto the operand
525          *                   stack which is assignable to the given {@code fieldType}.
526          * @param fieldType  The type of the field for storing the cached value. This field's type determines the value
527          *                   that is put onto the operand stack by this method's returned stack manipulation.
528          * @return A description of a field that was defined on the instrumented type which contains the given value.
529          */

530         FieldDescription.InDefinedShape cache(StackManipulation fieldValue, TypeDescription fieldType);
531
532         /**
533          * Returns the instrumented type of the current implementation. The instrumented type is exposed with the intend of allowing optimal
534          * byte code generation and not for implementing checks or changing the behavior of a {@link StackManipulation}.
535          *
536          * @return The instrumented type of the current implementation.
537          */

538         TypeDescription getInstrumentedType();
539
540         /**
541          * Returns the class file version of the currently created dynamic type.
542          *
543          * @return The class file version of the currently created dynamic type.
544          */

545         ClassFileVersion getClassFileVersion();
546
547         /**
548          * Represents an extractable view of an {@link Implementation.Context} which
549          * allows the retrieval of any registered auxiliary type.
550          */

551         interface ExtractableView extends Context {
552
553             /**
554              * Returns {@code trueif this implementation context permits the registration of any implicit type initializers.
555              *
556              * @return {@code trueif this implementation context permits the registration of any implicit type initializers.
557              */

558             boolean isEnabled();
559
560             /**
561              * Returns any {@link net.bytebuddy.implementation.auxiliary.AuxiliaryType} that was registered
562              * with this {@link Implementation.Context}.
563              *
564              * @return A list of all manifested registered auxiliary types.
565              */

566             List<DynamicType> getAuxiliaryTypes();
567
568             /**
569              * Writes any information that was registered with an {@link Implementation.Context}
570              * to the provided class visitor. This contains any fields for value caching, any accessor method and it
571              * writes the type initializer. The type initializer must therefore never be written manually.
572              *
573              * @param drain                        The drain to write the type initializer to.
574              * @param classVisitor                 The class visitor to which the extractable view is to be written.
575              * @param annotationValueFilterFactory The annotation value filter factory to apply when writing annotation.
576              */

577             void drain(TypeInitializer.Drain drain, ClassVisitor classVisitor, AnnotationValueFilter.Factory annotationValueFilterFactory);
578
579             /**
580              * An abstract base implementation of an extractable view of an implementation context.
581              */

582             @HashCodeAndEqualsPlugin.Enhance
583             abstract class AbstractBase implements ExtractableView {
584
585                 /**
586                  * The instrumented type.
587                  */

588                 protected final TypeDescription instrumentedType;
589
590                 /**
591                  * The class file version of the dynamic type.
592                  */

593                 protected final ClassFileVersion classFileVersion;
594
595                 /**
596                  * Create a new extractable view.
597                  *
598                  * @param instrumentedType The instrumented type.
599                  * @param classFileVersion The class file version of the dynamic type.
600                  */

601                 protected AbstractBase(TypeDescription instrumentedType, ClassFileVersion classFileVersion) {
602                     this.instrumentedType = instrumentedType;
603                     this.classFileVersion = classFileVersion;
604                 }
605
606                 /**
607                  * {@inheritDoc}
608                  */

609                 public TypeDescription getInstrumentedType() {
610                     return instrumentedType;
611                 }
612
613                 /**
614                  * {@inheritDoc}
615                  */

616                 public ClassFileVersion getClassFileVersion() {
617                     return classFileVersion;
618                 }
619             }
620         }
621
622         /**
623          * A factory for creating a new implementation context.
624          */

625         interface Factory {
626
627             /**
628              * Creates a new implementation context.
629              *
630              * @param instrumentedType            The description of the type that is currently subject of creation.
631              * @param auxiliaryTypeNamingStrategy The naming strategy for naming an auxiliary type.
632              * @param typeInitializer             The type initializer of the created instrumented type.
633              * @param classFileVersion            The class file version of the created class.
634              * @param auxiliaryClassFileVersion   The class file version of any auxiliary classes.
635              * @return An implementation context in its extractable view.
636              */

637             ExtractableView make(TypeDescription instrumentedType,
638                                  AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
639                                  TypeInitializer typeInitializer,
640                                  ClassFileVersion classFileVersion,
641                                  ClassFileVersion auxiliaryClassFileVersion);
642         }
643
644         /**
645          * An implementation context that does not allow for any injections into the static initializer block. This can be useful when
646          * redefining a class when it is not allowed to add methods to a class what is an implicit requirement when copying the static
647          * initializer block into another method.
648          */

649         class Disabled extends ExtractableView.AbstractBase {
650
651             /**
652              * Creates a new disabled implementation context.
653              *
654              * @param instrumentedType The instrumented type.
655              * @param classFileVersion The class file version to create the class in.
656              */

657             protected Disabled(TypeDescription instrumentedType, ClassFileVersion classFileVersion) {
658                 super(instrumentedType, classFileVersion);
659             }
660
661             /**
662              * {@inheritDoc}
663              */

664             public boolean isEnabled() {
665                 return false;
666             }
667
668             /**
669              * {@inheritDoc}
670              */

671             public List<DynamicType> getAuxiliaryTypes() {
672                 return Collections.emptyList();
673             }
674
675             /**
676              * {@inheritDoc}
677              */

678             public void drain(TypeInitializer.Drain drain, ClassVisitor classVisitor, AnnotationValueFilter.Factory annotationValueFilterFactory) {
679                 drain.apply(classVisitor, TypeInitializer.None.INSTANCE, this);
680             }
681
682             /**
683              * {@inheritDoc}
684              */

685             public TypeDescription register(AuxiliaryType auxiliaryType) {
686                 throw new IllegalStateException("Registration of auxiliary types was disabled: " + auxiliaryType);
687             }
688
689             /**
690              * {@inheritDoc}
691              */

692             public MethodDescription.InDefinedShape registerAccessorFor(SpecialMethodInvocation specialMethodInvocation, AccessType accessType) {
693                 throw new IllegalStateException("Registration of method accessors was disabled: " + specialMethodInvocation.getMethodDescription());
694             }
695
696             /**
697              * {@inheritDoc}
698              */

699             public MethodDescription.InDefinedShape registerGetterFor(FieldDescription fieldDescription, AccessType accessType) {
700                 throw new IllegalStateException("Registration of field accessor was disabled: " + fieldDescription);
701             }
702
703             /**
704              * {@inheritDoc}
705              */

706             public MethodDescription.InDefinedShape registerSetterFor(FieldDescription fieldDescription, AccessType accessType) {
707                 throw new IllegalStateException("Registration of field accessor was disabled: " + fieldDescription);
708             }
709
710             /**
711              * {@inheritDoc}
712              */

713             public FieldDescription.InDefinedShape cache(StackManipulation fieldValue, TypeDescription fieldType) {
714                 throw new IllegalStateException("Field values caching was disabled: " + fieldType);
715             }
716
717             /**
718              * A factory for creating a {@link net.bytebuddy.implementation.Implementation.Context.Disabled}.
719              */

720             public enum Factory implements Context.Factory {
721
722                 /**
723                  * The singleton instance.
724                  */

725                 INSTANCE;
726
727                 /**
728                  * {@inheritDoc}
729                  */

730                 public ExtractableView make(TypeDescription instrumentedType,
731                                             AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
732                                             TypeInitializer typeInitializer,
733                                             ClassFileVersion classFileVersion,
734                                             ClassFileVersion auxiliaryClassFileVersion) {
735                     if (typeInitializer.isDefined()) {
736                         throw new IllegalStateException("Cannot define type initializer which was explicitly disabled: " + typeInitializer);
737                     }
738                     return new Disabled(instrumentedType, classFileVersion);
739                 }
740             }
741         }
742
743         /**
744          * A default implementation of an {@link Implementation.Context.ExtractableView}
745          * which serves as its own {@link MethodAccessorFactory}.
746          */

747         class Default extends ExtractableView.AbstractBase {
748
749             /**
750              * The name suffix to be appended to an accessor method.
751              */

752             public static final String ACCESSOR_METHOD_SUFFIX = "accessor";
753
754             /**
755              * The name prefix to be prepended to a field storing a cached value.
756              */

757             public static final String FIELD_CACHE_PREFIX = "cachedValue";
758
759             /**
760              * The naming strategy for naming auxiliary types that are registered.
761              */

762             private final AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy;
763
764             /**
765              * The type initializer of the created instrumented type.
766              */

767             private final TypeInitializer typeInitializer;
768
769             /**
770              * The class file version to use for auxiliary classes.
771              */

772             private final ClassFileVersion auxiliaryClassFileVersion;
773
774             /**
775              * A mapping of special method invocations to their accessor methods that each invoke their mapped invocation.
776              */

777             private final Map<SpecialMethodInvocation, DelegationRecord> registeredAccessorMethods;
778
779             /**
780              * The registered getters.
781              */

782             private final Map<FieldDescription, DelegationRecord> registeredGetters;
783
784             /**
785              * The registered setters.
786              */

787             private final Map<FieldDescription, DelegationRecord> registeredSetters;
788
789             /**
790              * A map of registered auxiliary types to their dynamic type representation.
791              */

792             private final Map<AuxiliaryType, DynamicType> auxiliaryTypes;
793
794             /**
795              * A map of already registered field caches to their field representation.
796              */

797             private final Map<FieldCacheEntry, FieldDescription.InDefinedShape> registeredFieldCacheEntries;
798
799             /**
800              * A set of registered field cache entries.
801              */

802             private final Set<FieldDescription.InDefinedShape> registeredFieldCacheFields;
803
804             /**
805              * A random suffix to append to the names of accessor methods.
806              */

807             private final String suffix;
808
809             /**
810              * If {@code false}, the type initializer for this instance was already drained what prohibits the registration of additional cached field values.
811              */

812             private boolean fieldCacheCanAppendEntries;
813
814             /**
815              * Creates a new default implementation context.
816              *
817              * @param instrumentedType            The description of the type that is currently subject of creation.
818              * @param classFileVersion            The class file version of the created class.
819              * @param auxiliaryTypeNamingStrategy The naming strategy for naming an auxiliary type.
820              * @param typeInitializer             The type initializer of the created instrumented type.
821              * @param auxiliaryClassFileVersion   The class file version to use for auxiliary classes.
822              */

823             protected Default(TypeDescription instrumentedType,
824                               ClassFileVersion classFileVersion,
825                               AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
826                               TypeInitializer typeInitializer,
827                               ClassFileVersion auxiliaryClassFileVersion) {
828                 super(instrumentedType, classFileVersion);
829                 this.auxiliaryTypeNamingStrategy = auxiliaryTypeNamingStrategy;
830                 this.typeInitializer = typeInitializer;
831                 this.auxiliaryClassFileVersion = auxiliaryClassFileVersion;
832                 registeredAccessorMethods = new HashMap<SpecialMethodInvocation, DelegationRecord>();
833                 registeredGetters = new HashMap<FieldDescription, DelegationRecord>();
834                 registeredSetters = new HashMap<FieldDescription, DelegationRecord>();
835                 auxiliaryTypes = new HashMap<AuxiliaryType, DynamicType>();
836                 registeredFieldCacheEntries = new HashMap<FieldCacheEntry, FieldDescription.InDefinedShape>();
837                 registeredFieldCacheFields = new HashSet<FieldDescription.InDefinedShape>();
838                 suffix = RandomString.make();
839                 fieldCacheCanAppendEntries = true;
840             }
841
842             /**
843              * {@inheritDoc}
844              */

845             public boolean isEnabled() {
846                 return true;
847             }
848
849             /**
850              * {@inheritDoc}
851              */

852             public MethodDescription.InDefinedShape registerAccessorFor(SpecialMethodInvocation specialMethodInvocation, AccessType accessType) {
853                 DelegationRecord record = registeredAccessorMethods.get(specialMethodInvocation);
854                 record = record == null
855                         ? new AccessorMethodDelegation(instrumentedType, suffix, accessType, specialMethodInvocation)
856                         : record.with(accessType);
857                 registeredAccessorMethods.put(specialMethodInvocation, record);
858                 return record.getMethod();
859             }
860
861             /**
862              * {@inheritDoc}
863              */

864             public MethodDescription.InDefinedShape registerGetterFor(FieldDescription fieldDescription, AccessType accessType) {
865                 DelegationRecord record = registeredGetters.get(fieldDescription);
866                 record = record == null
867                         ? new FieldGetterDelegation(instrumentedType, suffix, accessType, fieldDescription)
868                         : record.with(accessType);
869                 registeredGetters.put(fieldDescription, record);
870                 return record.getMethod();
871             }
872
873             /**
874              * {@inheritDoc}
875              */

876             public MethodDescription.InDefinedShape registerSetterFor(FieldDescription fieldDescription, AccessType accessType) {
877                 DelegationRecord record = registeredSetters.get(fieldDescription);
878                 record = record == null
879                         ? new FieldSetterDelegation(instrumentedType, suffix, accessType, fieldDescription)
880                         : record.with(accessType);
881                 registeredSetters.put(fieldDescription, record);
882                 return record.getMethod();
883             }
884
885             /**
886              * {@inheritDoc}
887              */

888             public TypeDescription register(AuxiliaryType auxiliaryType) {
889                 DynamicType dynamicType = auxiliaryTypes.get(auxiliaryType);
890                 if (dynamicType == null) {
891                     dynamicType = auxiliaryType.make(auxiliaryTypeNamingStrategy.name(instrumentedType), auxiliaryClassFileVersion, this);
892                     auxiliaryTypes.put(auxiliaryType, dynamicType);
893                 }
894                 return dynamicType.getTypeDescription();
895             }
896
897             /**
898              * {@inheritDoc}
899              */

900             public List<DynamicType> getAuxiliaryTypes() {
901                 return new ArrayList<DynamicType>(auxiliaryTypes.values());
902             }
903
904             /**
905              * {@inheritDoc}
906              */

907             public FieldDescription.InDefinedShape cache(StackManipulation fieldValue, TypeDescription fieldType) {
908                 FieldCacheEntry fieldCacheEntry = new FieldCacheEntry(fieldValue, fieldType);
909                 FieldDescription.InDefinedShape fieldCache = registeredFieldCacheEntries.get(fieldCacheEntry);
910                 if (fieldCache != null) {
911                     return fieldCache;
912                 }
913                 if (!fieldCacheCanAppendEntries) {
914                     throw new IllegalStateException("Cached values cannot be registered after defining the type initializer for " + instrumentedType);
915                 }
916                 int hashCode = fieldValue.hashCode();
917                 do {
918                     fieldCache = new CacheValueField(instrumentedType, fieldType.asGenericType(), suffix, hashCode++);
919                 } while (!registeredFieldCacheFields.add(fieldCache));
920                 registeredFieldCacheEntries.put(fieldCacheEntry, fieldCache);
921                 return fieldCache;
922             }
923
924             /**
925              * {@inheritDoc}
926              */

927             public void drain(TypeInitializer.Drain drain,
928                               ClassVisitor classVisitor,
929                               AnnotationValueFilter.Factory annotationValueFilterFactory) {
930                 fieldCacheCanAppendEntries = false;
931                 TypeInitializer typeInitializer = this.typeInitializer;
932                 for (Map.Entry<FieldCacheEntry, FieldDescription.InDefinedShape> entry : registeredFieldCacheEntries.entrySet()) {
933                     FieldVisitor fieldVisitor = classVisitor.visitField(entry.getValue().getModifiers(),
934                             entry.getValue().getInternalName(),
935                             entry.getValue().getDescriptor(),
936                             entry.getValue().getGenericSignature(),
937                             FieldDescription.NO_DEFAULT_VALUE);
938                     if (fieldVisitor != null) {
939                         fieldVisitor.visitEnd();
940                         typeInitializer = typeInitializer.expandWith(entry.getKey().storeIn(entry.getValue()));
941                     }
942                 }
943                 drain.apply(classVisitor, typeInitializer, this);
944                 for (TypeWriter.MethodPool.Record record : registeredAccessorMethods.values()) {
945                     record.apply(classVisitor, this, annotationValueFilterFactory);
946                 }
947                 for (TypeWriter.MethodPool.Record record : registeredGetters.values()) {
948                     record.apply(classVisitor, this, annotationValueFilterFactory);
949                 }
950                 for (TypeWriter.MethodPool.Record record : registeredSetters.values()) {
951                     record.apply(classVisitor, this, annotationValueFilterFactory);
952                 }
953             }
954
955             /**
956              * A description of a field that stores a cached value.
957              */

958             protected static class CacheValueField extends FieldDescription.InDefinedShape.AbstractBase {
959
960                 /**
961                  * The instrumented type.
962                  */

963                 private final TypeDescription instrumentedType;
964
965                 /**
966                  * The type of the cache's field.
967                  */

968                 private final TypeDescription.Generic fieldType;
969
970                 /**
971                  * The name of the field.
972                  */

973                 private final String name;
974
975                 /**
976                  * Creates a new cache value field.
977                  *
978                  * @param instrumentedType The instrumented type.
979                  * @param fieldType        The type of the cache's field.
980                  * @param suffix           The suffix to use for the cache field's name.
981                  * @param hashCode         The hash value of the field's value for creating a unique field name.
982                  */

983                 protected CacheValueField(TypeDescription instrumentedType, TypeDescription.Generic fieldType, String suffix, int hashCode) {
984                     this.instrumentedType = instrumentedType;
985                     this.fieldType = fieldType;
986                     name = FIELD_CACHE_PREFIX + "$" + suffix + "$" + RandomString.hashOf(hashCode);
987                 }
988
989                 /**
990                  * {@inheritDoc}
991                  */

992                 public TypeDescription.Generic getType() {
993                     return fieldType;
994                 }
995
996                 /**
997                  * {@inheritDoc}
998                  */

999                 public AnnotationList getDeclaredAnnotations() {
1000                     return new AnnotationList.Empty();
1001                 }
1002
1003                 /**
1004                  * {@inheritDoc}
1005                  */

1006                 public TypeDescription getDeclaringType() {
1007                     return instrumentedType;
1008                 }
1009
1010                 /**
1011                  * {@inheritDoc}
1012                  */

1013                 public int getModifiers() {
1014                     return Opcodes.ACC_SYNTHETIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC | (instrumentedType.isInterface()
1015                             ? Opcodes.ACC_PUBLIC
1016                             : Opcodes.ACC_PRIVATE);
1017                 }
1018
1019                 /**
1020                  * {@inheritDoc}
1021                  */

1022                 public String getName() {
1023                     return name;
1024                 }
1025             }
1026
1027             /**
1028              * A field cache entry for uniquely identifying a cached field. A cached field is described by the stack
1029              * manipulation that loads the field's value onto the operand stack and the type of the field.
1030              */

1031             protected static class FieldCacheEntry implements StackManipulation {
1032
1033                 /**
1034                  * The field value that is represented by this field cache entry.
1035                  */

1036                 private final StackManipulation fieldValue;
1037
1038                 /**
1039                  * The field type that is represented by this field cache entry.
1040                  */

1041                 private final TypeDescription fieldType;
1042
1043                 /**
1044                  * Creates a new field cache entry.
1045                  *
1046                  * @param fieldValue The field value that is represented by this field cache entry.
1047                  * @param fieldType  The field type that is represented by this field cache entry.
1048                  */

1049                 protected FieldCacheEntry(StackManipulation fieldValue, TypeDescription fieldType) {
1050                     this.fieldValue = fieldValue;
1051                     this.fieldType = fieldType;
1052                 }
1053
1054                 /**
1055                  * Returns a stack manipulation where the represented value is stored in the given field.
1056                  *
1057                  * @param fieldDescription A static field in which the value is to be stored.
1058                  * @return A byte code appender that represents this storage.
1059                  */

1060                 protected ByteCodeAppender storeIn(FieldDescription fieldDescription) {
1061                     return new ByteCodeAppender.Simple(this, FieldAccess.forField(fieldDescription).write());
1062                 }
1063
1064                 /**
1065                  * Returns the field type that is represented by this field cache entry.
1066                  *
1067                  * @return The field type that is represented by this field cache entry.
1068                  */

1069                 protected TypeDescription getFieldType() {
1070                     return fieldType;
1071                 }
1072
1073                 /**
1074                  * {@inheritDoc}
1075                  */

1076                 public boolean isValid() {
1077                     return fieldValue.isValid();
1078                 }
1079
1080                 /**
1081                  * {@inheritDoc}
1082                  */

1083                 public Size apply(MethodVisitor methodVisitor, Context implementationContext) {
1084                     return fieldValue.apply(methodVisitor, implementationContext);
1085                 }
1086
1087                 @Override
1088                 public int hashCode() {
1089                     int result = fieldValue.hashCode();
1090                     result = 31 * result + fieldType.hashCode();
1091                     return result;
1092                 }
1093
1094                 @Override
1095                 public boolean equals(Object other) {
1096                     if (this == other) {
1097                         return true;
1098                     } else if (other == null || getClass() != other.getClass()) {
1099                         return false;
1100                     }
1101                     FieldCacheEntry fieldCacheEntry = (FieldCacheEntry) other;
1102                     return fieldValue.equals(fieldCacheEntry.fieldValue) && fieldType.equals(fieldCacheEntry.fieldType);
1103                 }
1104             }
1105
1106             /**
1107              * A base implementation of a method that accesses a property of an instrumented type.
1108              */

1109             protected abstract static class AbstractPropertyAccessorMethod extends MethodDescription.InDefinedShape.AbstractBase {
1110
1111                 /**
1112                  * {@inheritDoc}
1113                  */

1114                 public int getModifiers() {
1115                     return Opcodes.ACC_SYNTHETIC | getBaseModifiers() | (getDeclaringType().isInterface()
1116                             ? Opcodes.ACC_PUBLIC
1117                             : Opcodes.ACC_FINAL);
1118                 }
1119
1120                 /**
1121                  * Returns the base modifiers, i.e. the modifiers that define the accessed property's features.
1122                  *
1123                  * @return Returns the base modifiers of the represented methods.
1124                  */

1125                 protected abstract int getBaseModifiers();
1126             }
1127
1128             /**
1129              * A description of an accessor method to access another method from outside the instrumented type.
1130              */

1131             protected static class AccessorMethod extends AbstractPropertyAccessorMethod {
1132
1133                 /**
1134                  * The instrumented type.
1135                  */

1136                 private final TypeDescription instrumentedType;
1137
1138                 /**
1139                  * The method that is being accessed.
1140                  */

1141                 private final MethodDescription methodDescription;
1142
1143                 /**
1144                  * The name of the method.
1145                  */

1146                 private final String name;
1147
1148                 /**
1149                  * Creates a new accessor method.
1150                  *
1151                  * @param instrumentedType  The instrumented type.
1152                  * @param methodDescription The method that is being accessed.
1153                  * @param suffix            The suffix to append to the accessor method's name.
1154                  */

1155                 protected AccessorMethod(TypeDescription instrumentedType, MethodDescription methodDescription, String suffix) {
1156                     this.instrumentedType = instrumentedType;
1157                     this.methodDescription = methodDescription;
1158                     name = methodDescription.getInternalName() + "$" + ACCESSOR_METHOD_SUFFIX + "$" + suffix;
1159                 }
1160
1161                 /**
1162                  * {@inheritDoc}
1163                  */

1164                 public TypeDescription.Generic getReturnType() {
1165                     return methodDescription.getReturnType().asRawType();
1166                 }
1167
1168                 /**
1169                  * {@inheritDoc}
1170                  */

1171                 public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1172                     return new ParameterList.Explicit.ForTypes(this, methodDescription.getParameters().asTypeList().asRawTypes());
1173                 }
1174
1175                 /**
1176                  * {@inheritDoc}
1177                  */

1178                 public TypeList.Generic getExceptionTypes() {
1179                     return methodDescription.getExceptionTypes().asRawTypes();
1180                 }
1181
1182                 /**
1183                  * {@inheritDoc}
1184                  */

1185                 public AnnotationValue<?, ?> getDefaultValue() {
1186                     return AnnotationValue.UNDEFINED;
1187                 }
1188
1189                 /**
1190                  * {@inheritDoc}
1191                  */

1192                 public TypeList.Generic getTypeVariables() {
1193                     return new TypeList.Generic.Empty();
1194                 }
1195
1196                 /**
1197                  * {@inheritDoc}
1198                  */

1199                 public AnnotationList getDeclaredAnnotations() {
1200                     return new AnnotationList.Empty();
1201                 }
1202
1203                 /**
1204                  * {@inheritDoc}
1205                  */

1206                 public TypeDescription getDeclaringType() {
1207                     return instrumentedType;
1208                 }
1209
1210                 @Override
1211                 protected int getBaseModifiers() {
1212                     return methodDescription.isStatic()
1213                             ? Opcodes.ACC_STATIC
1214                             : EMPTY_MASK;
1215                 }
1216
1217                 /**
1218                  * {@inheritDoc}
1219                  */

1220                 public String getInternalName() {
1221                     return name;
1222                 }
1223             }
1224
1225             /**
1226              * A description of a field getter method.
1227              */

1228             protected static class FieldGetter extends AbstractPropertyAccessorMethod {
1229
1230                 /**
1231                  * The instrumented type.
1232                  */

1233                 private final TypeDescription instrumentedType;
1234
1235                 /**
1236                  * The field for which a getter is described.
1237                  */

1238                 private final FieldDescription fieldDescription;
1239
1240                 /**
1241                  * The name of the getter method.
1242                  */

1243                 private final String name;
1244
1245                 /**
1246                  * Creates a new field getter.
1247                  *
1248                  * @param instrumentedType The instrumented type.
1249                  * @param fieldDescription The field for which a getter is described.
1250                  * @param suffix           The name suffix for the field getter method.
1251                  */

1252                 protected FieldGetter(TypeDescription instrumentedType, FieldDescription fieldDescription, String suffix) {
1253                     this.instrumentedType = instrumentedType;
1254                     this.fieldDescription = fieldDescription;
1255                     name = fieldDescription.getName() + "$" + ACCESSOR_METHOD_SUFFIX + "$" + suffix;
1256                 }
1257
1258                 /**
1259                  * {@inheritDoc}
1260                  */

1261                 public TypeDescription.Generic getReturnType() {
1262                     return fieldDescription.getType().asRawType();
1263                 }
1264
1265                 /**
1266                  * {@inheritDoc}
1267                  */

1268                 public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1269                     return new ParameterList.Empty<ParameterDescription.InDefinedShape>();
1270                 }
1271
1272                 /**
1273                  * {@inheritDoc}
1274                  */

1275                 public TypeList.Generic getExceptionTypes() {
1276                     return new TypeList.Generic.Empty();
1277                 }
1278
1279                 /**
1280                  * {@inheritDoc}
1281                  */

1282                 public AnnotationValue<?, ?> getDefaultValue() {
1283                     return AnnotationValue.UNDEFINED;
1284                 }
1285
1286                 /**
1287                  * {@inheritDoc}
1288                  */

1289                 public TypeList.Generic getTypeVariables() {
1290                     return new TypeList.Generic.Empty();
1291                 }
1292
1293                 /**
1294                  * {@inheritDoc}
1295                  */

1296                 public AnnotationList getDeclaredAnnotations() {
1297                     return new AnnotationList.Empty();
1298                 }
1299
1300                 /**
1301                  * {@inheritDoc}
1302                  */

1303                 public TypeDescription getDeclaringType() {
1304                     return instrumentedType;
1305                 }
1306
1307                 @Override
1308                 protected int getBaseModifiers() {
1309                     return fieldDescription.isStatic()
1310                             ? Opcodes.ACC_STATIC
1311                             : EMPTY_MASK;
1312                 }
1313
1314                 /**
1315                  * {@inheritDoc}
1316                  */

1317                 public String getInternalName() {
1318                     return name;
1319                 }
1320             }
1321
1322             /**
1323              * A description of a field setter method.
1324              */

1325             protected static class FieldSetter extends AbstractPropertyAccessorMethod {
1326
1327                 /**
1328                  * The instrumented type.
1329                  */

1330                 private final TypeDescription instrumentedType;
1331
1332                 /**
1333                  * The field for which a setter is described.
1334                  */

1335                 private final FieldDescription fieldDescription;
1336
1337                 /**
1338                  * The name of the field setter.
1339                  */

1340                 private final String name;
1341
1342                 /**
1343                  * Creates a new field setter.
1344                  *
1345                  * @param instrumentedType The instrumented type.
1346                  * @param fieldDescription The field for which a setter is described.
1347                  * @param suffix           The name suffix for the field setter method.
1348                  */

1349                 protected FieldSetter(TypeDescription instrumentedType, FieldDescription fieldDescription, String suffix) {
1350                     this.instrumentedType = instrumentedType;
1351                     this.fieldDescription = fieldDescription;
1352                     name = fieldDescription.getName() + "$" + ACCESSOR_METHOD_SUFFIX + "$" + suffix;
1353                 }
1354
1355                 /**
1356                  * {@inheritDoc}
1357                  */

1358                 public TypeDescription.Generic getReturnType() {
1359                     return TypeDescription.Generic.VOID;
1360                 }
1361
1362                 /**
1363                  * {@inheritDoc}
1364                  */

1365                 public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1366                     return new ParameterList.Explicit.ForTypes(this, Collections.singletonList(fieldDescription.getType().asRawType()));
1367                 }
1368
1369                 /**
1370                  * {@inheritDoc}
1371                  */

1372                 public TypeList.Generic getExceptionTypes() {
1373                     return new TypeList.Generic.Empty();
1374                 }
1375
1376                 /**
1377                  * {@inheritDoc}
1378                  */

1379                 public AnnotationValue<?, ?> getDefaultValue() {
1380                     return AnnotationValue.UNDEFINED;
1381                 }
1382
1383                 /**
1384                  * {@inheritDoc}
1385                  */

1386                 public TypeList.Generic getTypeVariables() {
1387                     return new TypeList.Generic.Empty();
1388                 }
1389
1390                 /**
1391                  * {@inheritDoc}
1392                  */

1393                 public AnnotationList getDeclaredAnnotations() {
1394                     return new AnnotationList.Empty();
1395                 }
1396
1397                 /**
1398                  * {@inheritDoc}
1399                  */

1400                 public TypeDescription getDeclaringType() {
1401                     return instrumentedType;
1402                 }
1403
1404                 @Override
1405                 protected int getBaseModifiers() {
1406                     return fieldDescription.isStatic()
1407                             ? Opcodes.ACC_STATIC
1408                             : EMPTY_MASK;
1409                 }
1410
1411                 /**
1412                  * {@inheritDoc}
1413                  */

1414                 public String getInternalName() {
1415                     return name;
1416                 }
1417             }
1418
1419             /**
1420              * An abstract method pool entry that delegates the implementation of a method to itself.
1421              */

1422             @HashCodeAndEqualsPlugin.Enhance
1423             protected abstract static class DelegationRecord extends TypeWriter.MethodPool.Record.ForDefinedMethod implements ByteCodeAppender {
1424
1425                 /**
1426                  * The delegation method.
1427                  */

1428                 protected final MethodDescription.InDefinedShape methodDescription;
1429
1430                 /**
1431                  * The record's visibility.
1432                  */

1433                 protected final Visibility visibility;
1434
1435                 /**
1436                  * Creates a new delegation record.
1437                  *
1438                  * @param methodDescription The delegation method.
1439                  * @param visibility        The method's actual visibility.
1440                  */

1441                 protected DelegationRecord(MethodDescription.InDefinedShape methodDescription, Visibility visibility) {
1442                     this.methodDescription = methodDescription;
1443                     this.visibility = visibility;
1444                 }
1445
1446                 /**
1447                  * Returns this delegation record with the minimal visibility represented by the supplied access type.
1448                  *
1449                  * @param accessType The access type to enforce.
1450                  * @return A new version of this delegation record with the minimal implied visibility.
1451                  */

1452                 protected abstract DelegationRecord with(AccessType accessType);
1453
1454                 /**
1455                  * {@inheritDoc}
1456                  */

1457                 public MethodDescription.InDefinedShape getMethod() {
1458                     return methodDescription;
1459                 }
1460
1461                 /**
1462                  * {@inheritDoc}
1463                  */

1464                 public Sort getSort() {
1465                     return Sort.IMPLEMENTED;
1466                 }
1467
1468                 /**
1469                  * {@inheritDoc}
1470                  */

1471                 public Visibility getVisibility() {
1472                     return visibility;
1473                 }
1474
1475                 /**
1476                  * {@inheritDoc}
1477                  */

1478                 public void applyHead(MethodVisitor methodVisitor) {
1479                     /* do nothing */
1480                 }
1481
1482                 /**
1483                  * {@inheritDoc}
1484                  */

1485                 public void applyBody(MethodVisitor methodVisitor, Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory) {
1486                     methodVisitor.visitCode();
1487                     Size size = applyCode(methodVisitor, implementationContext);
1488                     methodVisitor.visitMaxs(size.getOperandStackSize(), size.getLocalVariableSize());
1489                 }
1490
1491                 /**
1492                  * {@inheritDoc}
1493                  */

1494                 public void applyAttributes(MethodVisitor methodVisitor, AnnotationValueFilter.Factory annotationValueFilterFactory) {
1495                     /* do nothing */
1496                 }
1497
1498                 /**
1499                  * {@inheritDoc}
1500                  */

1501                 public Size applyCode(MethodVisitor methodVisitor, Context implementationContext) {
1502                     return apply(methodVisitor, implementationContext, getMethod());
1503                 }
1504
1505                 /**
1506                  * {@inheritDoc}
1507                  */

1508                 public TypeWriter.MethodPool.Record prepend(ByteCodeAppender byteCodeAppender) {
1509                     throw new UnsupportedOperationException("Cannot prepend code to a delegation for " + methodDescription);
1510                 }
1511             }
1512
1513             /**
1514              * An implementation of a {@link TypeWriter.MethodPool.Record} for implementing
1515              * an accessor method.
1516              */

1517             @HashCodeAndEqualsPlugin.Enhance
1518             protected static class AccessorMethodDelegation extends DelegationRecord {
1519
1520                 /**
1521                  * The stack manipulation that represents the requested special method invocation.
1522                  */

1523                 private final StackManipulation accessorMethodInvocation;
1524
1525                 /**
1526                  * Creates a delegation to an accessor method.
1527                  *
1528                  * @param instrumentedType        The instrumented type.
1529                  * @param suffix                  The suffix to append to the method.
1530                  * @param accessType              The access type.
1531                  * @param specialMethodInvocation The actual method's invocation.
1532                  */

1533                 protected AccessorMethodDelegation(TypeDescription instrumentedType,
1534                                                    String suffix,
1535                                                    AccessType accessType,
1536                                                    SpecialMethodInvocation specialMethodInvocation) {
1537                     this(new AccessorMethod(instrumentedType, specialMethodInvocation.getMethodDescription(), suffix),
1538                             accessType.getVisibility(),
1539                             specialMethodInvocation);
1540                 }
1541
1542                 /**
1543                  * Creates a delegation to an accessor method.
1544                  *
1545                  * @param methodDescription        The accessor method.
1546                  * @param visibility               The method's visibility.
1547                  * @param accessorMethodInvocation The actual method's invocation.
1548                  */

1549                 private AccessorMethodDelegation(MethodDescription.InDefinedShape methodDescription,
1550                                                  Visibility visibility,
1551                                                  StackManipulation accessorMethodInvocation) {
1552                     super(methodDescription, visibility);
1553                     this.accessorMethodInvocation = accessorMethodInvocation;
1554                 }
1555
1556                 @Override
1557                 protected DelegationRecord with(AccessType accessType) {
1558                     return new AccessorMethodDelegation(methodDescription, visibility.expandTo(accessType.getVisibility()), accessorMethodInvocation);
1559                 }
1560
1561                 /**
1562                  * {@inheritDoc}
1563                  */

1564                 public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) {
1565                     StackManipulation.Size stackSize = new StackManipulation.Compound(
1566                             MethodVariableAccess.allArgumentsOf(instrumentedMethod).prependThisReference(),
1567                             accessorMethodInvocation,
1568                             MethodReturn.of(instrumentedMethod.getReturnType())
1569                     ).apply(methodVisitor, implementationContext);
1570                     return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
1571                 }
1572             }
1573
1574             /**
1575              * An implementation for a field getter.
1576              */

1577             @HashCodeAndEqualsPlugin.Enhance
1578             protected static class FieldGetterDelegation extends DelegationRecord {
1579
1580                 /**
1581                  * The field to read from.
1582                  */

1583                 private final FieldDescription fieldDescription;
1584
1585                 /**
1586                  * Creates a new field getter implementation.
1587                  *
1588                  * @param instrumentedType The instrumented type.
1589                  * @param suffix           The suffix to use for the setter method.
1590                  * @param accessType       The method's access type.
1591                  * @param fieldDescription The field to write to.
1592                  */

1593                 protected FieldGetterDelegation(TypeDescription instrumentedType, String suffix, AccessType accessType, FieldDescription fieldDescription) {
1594                     this(new FieldGetter(instrumentedType, fieldDescription, suffix), accessType.getVisibility(), fieldDescription);
1595                 }
1596
1597                 /**
1598                  * Creates a new field getter implementation.
1599                  *
1600                  * @param methodDescription The delegation method.
1601                  * @param visibility        The delegation method's visibility.
1602                  * @param fieldDescription  The field to read.
1603                  */

1604                 private FieldGetterDelegation(MethodDescription.InDefinedShape methodDescription, Visibility visibility, FieldDescription fieldDescription) {
1605                     super(methodDescription, visibility);
1606                     this.fieldDescription = fieldDescription;
1607                 }
1608
1609                 @Override
1610                 protected DelegationRecord with(AccessType accessType) {
1611                     return new FieldGetterDelegation(methodDescription, visibility.expandTo(accessType.getVisibility()), fieldDescription);
1612                 }
1613
1614                 /**
1615                  * {@inheritDoc}
1616                  */

1617                 public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1618                     StackManipulation.Size stackSize = new StackManipulation.Compound(
1619                             fieldDescription.isStatic()
1620                                     ? StackManipulation.Trivial.INSTANCE
1621                                     : MethodVariableAccess.loadThis(),
1622                             FieldAccess.forField(fieldDescription).read(),
1623                             MethodReturn.of(fieldDescription.getType())
1624                     ).apply(methodVisitor, implementationContext);
1625                     return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
1626                 }
1627             }
1628
1629             /**
1630              * An implementation for a field setter.
1631              */

1632             @HashCodeAndEqualsPlugin.Enhance
1633             protected static class FieldSetterDelegation extends DelegationRecord {
1634
1635                 /**
1636                  * The field to write to.
1637                  */

1638                 private final FieldDescription fieldDescription;
1639
1640                 /**
1641                  * Creates a new field setter implementation.
1642                  *
1643                  * @param instrumentedType The instrumented type.
1644                  * @param suffix           The suffix to use for the setter method.
1645                  * @param accessType       The method's access type.
1646                  * @param fieldDescription The field to write to.
1647                  */

1648                 protected FieldSetterDelegation(TypeDescription instrumentedType, String suffix, AccessType accessType, FieldDescription fieldDescription) {
1649                     this(new FieldSetter(instrumentedType, fieldDescription, suffix), accessType.getVisibility(), fieldDescription);
1650                 }
1651
1652                 /**
1653                  * Creates a new field setter.
1654                  *
1655                  * @param methodDescription The field accessor method.
1656                  * @param visibility        The delegation method's visibility.
1657                  * @param fieldDescription  The field to write to.
1658                  */

1659                 private FieldSetterDelegation(MethodDescription.InDefinedShape methodDescription, Visibility visibility, FieldDescription fieldDescription) {
1660                     super(methodDescription, visibility);
1661                     this.fieldDescription = fieldDescription;
1662                 }
1663
1664                 @Override
1665                 protected DelegationRecord with(AccessType accessType) {
1666                     return new FieldSetterDelegation(methodDescription, visibility.expandTo(accessType.getVisibility()), fieldDescription);
1667                 }
1668
1669                 /**
1670                  * {@inheritDoc}
1671                  */

1672                 public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1673                     StackManipulation.Size stackSize = new StackManipulation.Compound(
1674                             MethodVariableAccess.allArgumentsOf(instrumentedMethod).prependThisReference(),
1675                             FieldAccess.forField(fieldDescription).write(),
1676                             MethodReturn.VOID
1677                     ).apply(methodVisitor, implementationContext);
1678                     return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
1679                 }
1680             }
1681
1682             /**
1683              * A factory for creating a {@link net.bytebuddy.implementation.Implementation.Context.Default}.
1684              */

1685             public enum Factory implements ExtractableView.Factory {
1686
1687                 /**
1688                  * The singleton instance.
1689                  */

1690                 INSTANCE;
1691
1692                 /**
1693                  * {@inheritDoc}
1694                  */

1695                 public ExtractableView make(TypeDescription instrumentedType,
1696                                             AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
1697                                             TypeInitializer typeInitializer,
1698                                             ClassFileVersion classFileVersion,
1699                                             ClassFileVersion auxiliaryClassFileVersion) {
1700                     return new Default(instrumentedType, classFileVersion, auxiliaryTypeNamingStrategy, typeInitializer, auxiliaryClassFileVersion);
1701                 }
1702             }
1703         }
1704     }
1705
1706     /**
1707      * A compound implementation that allows to combine several implementations.
1708      * <p>&nbsp;</p>
1709      * Note that the combination of two implementation might break the contract for implementing
1710      * {@link java.lang.Object#equals(Object)} and {@link Object#hashCode()} as described for
1711      * {@link Implementation}.
1712      *
1713      * @see Implementation
1714      */

1715     @HashCodeAndEqualsPlugin.Enhance
1716     class Compound implements Implementation {
1717
1718         /**
1719          * All implementation that are represented by this compound implementation.
1720          */

1721         private final List<Implementation> implementations;
1722
1723         /**
1724          * Creates a new immutable compound implementation.
1725          *
1726          * @param implementation The implementations to combine in their order.
1727          */

1728         public Compound(Implementation... implementation) {
1729             this(Arrays.asList(implementation));
1730         }
1731
1732         /**
1733          * Creates a new immutable compound implementation.
1734          *
1735          * @param implementations The implementations to combine in their order.
1736          */

1737         public Compound(List<? extends Implementation> implementations) {
1738             this.implementations = new ArrayList<Implementation>();
1739             for (Implementation implementation : implementations) {
1740                 if (implementation instanceof Compound.Composable) {
1741                     this.implementations.addAll(((Compound.Composable) implementation).implementations);
1742                     this.implementations.add(((Compound.Composable) implementation).composable);
1743                 } else if (implementation instanceof Compound) {
1744                     this.implementations.addAll(((Compound) implementation).implementations);
1745                 } else {
1746                     this.implementations.add(implementation);
1747                 }
1748             }
1749         }
1750
1751         /**
1752          * {@inheritDoc}
1753          */

1754         public InstrumentedType prepare(InstrumentedType instrumentedType) {
1755             for (Implementation implementation : implementations) {
1756                 instrumentedType = implementation.prepare(instrumentedType);
1757             }
1758             return instrumentedType;
1759         }
1760
1761         /**
1762          * {@inheritDoc}
1763          */

1764         public ByteCodeAppender appender(Target implementationTarget) {
1765             ByteCodeAppender[] byteCodeAppender = new ByteCodeAppender[implementations.size()];
1766             int index = 0;
1767             for (Implementation implementation : implementations) {
1768                 byteCodeAppender[index++] = implementation.appender(implementationTarget);
1769             }
1770             return new ByteCodeAppender.Compound(byteCodeAppender);
1771         }
1772
1773         /**
1774          * A compound implementation that allows to combine several implementations and that is {@link Implementation.Composable}.
1775          * <p>&nbsp;</p>
1776          * Note that the combination of two implementation might break the contract for implementing
1777          * {@link java.lang.Object#equals(Object)} and {@link Object#hashCode()} as described for
1778          * {@link Implementation}.
1779          *
1780          * @see Implementation
1781          */

1782         @HashCodeAndEqualsPlugin.Enhance
1783         public static class Composable implements Implementation.Composable {
1784
1785             /**
1786              * The composable implementation that is applied last.
1787              */

1788             private final Implementation.Composable composable;
1789
1790             /**
1791              * All implementation that are represented by this compound implementation.
1792              */

1793             private final List<Implementation> implementations;
1794
1795             /**
1796              * Creates a new compound composable.
1797              *
1798              * @param implementation An implementation that is represented by this compound implementation prior to the composable.
1799              * @param composable     The composable implementation that is applied last.
1800              */

1801             public Composable(Implementation implementation, Implementation.Composable composable) {
1802                 this(Collections.singletonList(implementation), composable);
1803             }
1804
1805             /**
1806              * Creates a new compound composable.
1807              *
1808              * @param implementations All implementation that are represented by this compound implementation excluding the composable.
1809              * @param composable      The composable implementation that is applied last.
1810              */

1811             public Composable(List<? extends Implementation> implementations, Implementation.Composable composable) {
1812                 this.implementations = new ArrayList<Implementation>();
1813                 for (Implementation implementation : implementations) {
1814                     if (implementation instanceof Compound.Composable) {
1815                         this.implementations.addAll(((Compound.Composable) implementation).implementations);
1816                         this.implementations.add(((Compound.Composable) implementation).composable);
1817                     } else if (implementation instanceof Compound) {
1818                         this.implementations.addAll(((Compound) implementation).implementations);
1819                     } else {
1820                         this.implementations.add(implementation);
1821                     }
1822                 }
1823                 if (composable instanceof Compound.Composable) {
1824                     this.implementations.addAll(((Compound.Composable) composable).implementations);
1825                     this.composable = ((Compound.Composable) composable).composable;
1826                 } else {
1827                     this.composable = composable;
1828                 }
1829             }
1830
1831             /**
1832              * {@inheritDoc}
1833              */

1834             public InstrumentedType prepare(InstrumentedType instrumentedType) {
1835                 for (Implementation implementation : implementations) {
1836                     instrumentedType = implementation.prepare(instrumentedType);
1837                 }
1838                 return composable.prepare(instrumentedType);
1839             }
1840
1841             /**
1842              * {@inheritDoc}
1843              */

1844             public ByteCodeAppender appender(Target implementationTarget) {
1845                 ByteCodeAppender[] byteCodeAppender = new ByteCodeAppender[implementations.size() + 1];
1846                 int index = 0;
1847                 for (Implementation implementation : implementations) {
1848                     byteCodeAppender[index++] = implementation.appender(implementationTarget);
1849                 }
1850                 byteCodeAppender[index] = composable.appender(implementationTarget);
1851                 return new ByteCodeAppender.Compound(byteCodeAppender);
1852             }
1853
1854             /**
1855              * {@inheritDoc}
1856              */

1857             public Implementation andThen(Implementation implementation) {
1858                 return new Compound(CompoundList.of(implementations, composable.andThen(implementation)));
1859             }
1860
1861             /**
1862              * {@inheritDoc}
1863              */

1864             public Implementation.Composable andThen(Implementation.Composable implementation) {
1865                 return new Compound.Composable(implementations, composable.andThen(implementation));
1866             }
1867         }
1868     }
1869
1870     /**
1871      * A simple implementation that does not register any members with the instrumented type.
1872      */

1873     @HashCodeAndEqualsPlugin.Enhance
1874     class Simple implements Implementation {
1875
1876         /**
1877          * The byte code appender to emmit.
1878          */

1879         private final ByteCodeAppender byteCodeAppender;
1880
1881         /**
1882          * Creates a new simple implementation for the given byte code appenders.
1883          *
1884          * @param byteCodeAppender The byte code appenders to apply in their order of application.
1885          */

1886         public Simple(ByteCodeAppender... byteCodeAppender) {
1887             this.byteCodeAppender = new ByteCodeAppender.Compound(byteCodeAppender);
1888         }
1889
1890         /**
1891          * Creates a new simple instrumentation for the given stack manipulations which are summarized in a
1892          * byte code appender that defines any requested method by these manipulations.
1893          *
1894          * @param stackManipulation The stack manipulation to apply in their order of application.
1895          */

1896         public Simple(StackManipulation... stackManipulation) {
1897             byteCodeAppender = new ByteCodeAppender.Simple(stackManipulation);
1898         }
1899
1900         /**
1901          * {@inheritDoc}
1902          */

1903         public InstrumentedType prepare(InstrumentedType instrumentedType) {
1904             return instrumentedType;
1905         }
1906
1907         /**
1908          * {@inheritDoc}
1909          */

1910         public ByteCodeAppender appender(Target implementationTarget) {
1911             return byteCodeAppender;
1912         }
1913     }
1914 }
1915