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.auxiliary;
17
18 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19 import net.bytebuddy.ClassFileVersion;
20 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
21 import net.bytebuddy.description.modifier.ModifierContributor;
22 import net.bytebuddy.description.modifier.SyntheticState;
23 import net.bytebuddy.description.type.TypeDescription;
24 import net.bytebuddy.dynamic.DynamicType;
25 import net.bytebuddy.implementation.MethodAccessorFactory;
26 import net.bytebuddy.utility.RandomString;
27
28 import java.lang.annotation.ElementType;
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.lang.annotation.Target;
32
33 /**
34 * An auxiliary type that provides services to the instrumentation of another type. Implementations should provide
35 * meaningful {@code equals(Object)} and {@code hashCode()} implementations in order to avoid multiple creations
36 * of this type.
37 */
38 public interface AuxiliaryType {
39
40 /**
41 * The default type access of an auxiliary type. <b>This array must not be mutated</b>.
42 */
43 @SuppressFBWarnings(value = {"MS_MUTABLE_ARRAY", "MS_OOI_PKGPROTECT"}, justification = "The array is not to be modified by contract")
44 ModifierContributor.ForType[] DEFAULT_TYPE_MODIFIER = {SyntheticState.SYNTHETIC};
45
46 /**
47 * Creates a new auxiliary type.
48 *
49 * @param auxiliaryTypeName The fully qualified binary name for this auxiliary type. The type should be in
50 * the same package than the instrumented type this auxiliary type is providing services
51 * to in order to allow package-private access.
52 * @param classFileVersion The class file version the auxiliary class should be written in.
53 * @param methodAccessorFactory A factory for accessor methods.
54 * @return A dynamically created type representing this auxiliary type.
55 */
56 DynamicType make(String auxiliaryTypeName, ClassFileVersion classFileVersion, MethodAccessorFactory methodAccessorFactory);
57
58 /**
59 * Representation of a naming strategy for an auxiliary type.
60 */
61 interface NamingStrategy {
62
63 /**
64 * Names an auxiliary type.
65 *
66 * @param instrumentedType The instrumented type for which an auxiliary type is registered.
67 * @return The fully qualified name for the given auxiliary type.
68 */
69 String name(TypeDescription instrumentedType);
70
71 /**
72 * A naming strategy for an auxiliary type which returns the instrumented type's name with a fixed extension
73 * and a random number as a suffix. All generated names will be in the same package as the instrumented type.
74 */
75 @HashCodeAndEqualsPlugin.Enhance
76 class SuffixingRandom implements NamingStrategy {
77
78 /**
79 * The suffix to append to the instrumented type for creating names for the auxiliary types.
80 */
81 private final String suffix;
82
83 /**
84 * An instance for creating random values.
85 */
86 @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.IGNORE)
87 private final RandomString randomString;
88
89 /**
90 * Creates a new suffixing random naming strategy.
91 *
92 * @param suffix The suffix to extend to the instrumented type.
93 */
94 public SuffixingRandom(String suffix) {
95 this.suffix = suffix;
96 randomString = new RandomString();
97 }
98
99 /**
100 * {@inheritDoc}
101 */
102 public String name(TypeDescription instrumentedType) {
103 return instrumentedType.getName() + "$" + suffix + "$" + randomString.nextString();
104 }
105 }
106 }
107
108 /**
109 * A marker to indicate that an auxiliary type is part of the instrumented types signature. This information can be used to load a type before
110 * the instrumented type such that reflection on the instrumented type does not cause a {@link NoClassDefFoundError}.
111 */
112 @Retention(RetentionPolicy.CLASS)
113 @Target(ElementType.TYPE)
114 @interface SignatureRelevant {
115 /* empty */
116 }
117 }
118