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.utility;
17
18 import net.bytebuddy.build.CachedReturnPlugin;
19 import net.bytebuddy.description.type.TypeDefinition;
20 import net.bytebuddy.description.type.TypeDescription;
21 import net.bytebuddy.description.type.TypeList;
22 import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
23 import net.bytebuddy.jar.asm.Opcodes;
24
25 import java.io.Serializable;
26 import java.lang.reflect.*;
27
28 /**
29  * Representations of Java types that do not exist in Java 6 but that have a special meaning to the JVM.
30  */

31 public enum JavaType {
32
33     /**
34      * The Java 12 {@code java.lang.constant.Constable} type.
35      */

36     CONSTABLE("java.lang.constant.Constable", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE, TypeDescription.UNDEFINED),
37
38     /**
39      * The Java 12 {@code java.lang.invoke.TypeDescriptor} type.
40      */

41     TYPE_DESCRIPTOR("java.lang.invoke.TypeDescriptor", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE, TypeDescription.UNDEFINED),
42
43     /**
44      * The Java 12 {@code java.lang.invoke.TypeDescriptor$OfMethod} type.
45      */

46     TYPE_DESCRIPTOR_OF_FIELD("java.lang.invoke.TypeDescriptor$OfField",
47             Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
48             TypeDescription.UNDEFINED,
49             TYPE_DESCRIPTOR.getTypeStub()),
50
51     /**
52      * The Java 12 {@code java.lang.invoke.TypeDescriptor$OfMethod} type.
53      */

54     TYPE_DESCRIPTOR_OF_METHOD("java.lang.invoke.TypeDescriptor$OfMethod",
55             Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
56             TypeDescription.UNDEFINED,
57             TYPE_DESCRIPTOR.getTypeStub()),
58
59     /**
60      * The Java 12 {@code java.lang.constant.ConstableDesc} type.
61      */

62     CONSTANT_DESCRIPTION("java.lang.constant.ConstantDesc", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE, TypeDescription.UNDEFINED),
63
64     /**
65      * The Java 12 {@code java.lang.constant.DynamicConstantDesc} type.
66      */

67     DYNAMIC_CONSTANT_DESCRIPTION("java.lang.constant.DynamicConstantDesc",
68             Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
69             TypeDescription.OBJECT,
70             CONSTANT_DESCRIPTION.getTypeStub()),
71
72     /**
73      * The Java 12 {@code java.lang.constant.ClassDesc} type.
74      */

75     CLASS_DESCRIPTION("java.lang.constant.ClassDesc",
76             Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
77             TypeDescription.UNDEFINED,
78             CONSTANT_DESCRIPTION.getTypeStub(),
79             TYPE_DESCRIPTOR_OF_FIELD.getTypeStub()),
80
81     /**
82      * The Java 12 {@code java.lang.constant.MethodTypeDesc} type.
83      */

84     METHOD_TYPE_DESCRIPTION("java.lang.constant.MethodTypeDesc",
85             Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
86             TypeDescription.UNDEFINED,
87             CONSTANT_DESCRIPTION.getTypeStub(),
88             TYPE_DESCRIPTOR_OF_METHOD.getTypeStub()),
89
90     /**
91      * The Java 12 {@code java.lang.constant.MethodHandleDesc} type.
92      */

93     METHOD_HANDLE_DESCRIPTION("java.lang.constant.MethodHandleDesc",
94             Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
95             TypeDescription.UNDEFINED,
96             CONSTANT_DESCRIPTION.getTypeStub()),
97
98     /**
99      * The Java 12 {@code java.lang.constant.DirectMethodHandleDesc} type.
100      */

101     DIRECT_METHOD_HANDLE_DESCRIPTION("java.lang.constant.DirectMethodHandleDesc",
102             Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
103             TypeDescription.UNDEFINED,
104             METHOD_HANDLE_DESCRIPTION.getTypeStub()),
105
106     /**
107      * The Java 7 {@code java.lang.invoke.MethodHandle} type.
108      */

109     METHOD_HANDLE("java.lang.invoke.MethodHandle", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, TypeDescription.OBJECT, CONSTABLE.getTypeStub()),
110
111     /**
112      * The Java 7 {@code java.lang.invoke.MethodHandles} type.
113      */

114     METHOD_HANDLES("java.lang.invoke.MethodHandles", Opcodes.ACC_PUBLIC, Object.class),
115
116     /**
117      * The Java 7 {@code java.lang.invoke.MethodType} type.
118      */

119     METHOD_TYPE("java.lang.invoke.MethodType",
120             Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
121             TypeDescription.OBJECT,
122             CONSTABLE.getTypeStub(),
123             TYPE_DESCRIPTOR_OF_METHOD.getTypeStub(),
124             TypeDescription.ForLoadedType.of(Serializable.class)),
125
126     /**
127      * The Java 7 {@code java.lang.invoke.MethodTypes.Lookup} type.
128      */

129     METHOD_HANDLES_LOOKUP("java.lang.invoke.MethodHandles$Lookup", Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, Object.class),
130
131     /**
132      * The Java 7 {@code java.lang.invoke.CallSite} type.
133      */

134     CALL_SITE("java.lang.invoke.CallSite", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, Object.class),
135
136     /**
137      * The Java 9 {@code java.lang.invoke.VarHandle} type.
138      */

139     VAR_HANDLE("java.lang.invoke.VarHandle", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, TypeDescription.Generic.OBJECT, CONSTABLE.getTypeStub()),
140
141     /**
142      * The Java 8 {@code java.lang.reflect.Parameter} type.
143      */

144     PARAMETER("java.lang.reflect.Parameter", Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, Object.class, AnnotatedElement.class),
145
146     /**
147      * The Java 7 {@code java.lang.reflect.Executable} type.
148      */

149     EXECUTABLE("java.lang.reflect.Executable", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, AccessibleObject.class, Member.class, GenericDeclaration.class),
150
151     /**
152      * The Java 9 {@code java.lang.Module} type.
153      */

154     MODULE("java.lang.Module", Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, Object.class, AnnotatedElement.class),
155
156     /**
157      * The Java 14 {@code java.lang.Record} type.
158      */

159     RECORD("java.lang.Record", Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, Object.class),
160
161     /**
162      * The Java 14 {@code java.lang.runtime.ObjectMethods} type.
163      */

164     OBJECT_METHODS("java.lang.runtime.ObjectMethods", Opcodes.ACC_PUBLIC, Object.class);
165
166     /**
167      * The type description to represent this type which is either a loaded type or a stub.
168      */

169     private final TypeDescription typeDescription;
170
171     /**
172      * Creates a new java type representation.
173      *
174      * @param typeName    The binary name of this type.
175      * @param modifiers   The modifiers of this type when creating a stub.
176      * @param superClass  The super class of this type when creating a stub.
177      * @param anInterface The interfaces of this type when creating a stub.
178      */

179     JavaType(String typeName, int modifiers, Type superClass, Type... anInterface) {
180         this(typeName, modifiers, superClass == null
181                 ? TypeDescription.Generic.UNDEFINED
182                 : TypeDescription.Generic.Sort.describe(superClass), new TypeList.Generic.ForLoadedTypes(anInterface));
183     }
184
185     /**
186      * Creates a new java type representation.
187      *
188      * @param typeName    The binary name of this type.
189      * @param modifiers   The modifiers of this type when creating a stub.
190      * @param superClass  The super class of this type when creating a stub.
191      * @param anInterface The interfaces of this type when creating a stub.
192      */

193     JavaType(String typeName, int modifiers, TypeDefinition superClass, TypeDefinition... anInterface) {
194         this(typeName, modifiers, superClass == null
195                 ? TypeDescription.Generic.UNDEFINED
196                 : superClass.asGenericType(), new TypeList.Generic.Explicit(anInterface));
197     }
198
199     /**
200      * Creates a new java type representation.
201      *
202      * @param typeName   The binary name of this type.
203      * @param modifiers  The modifiers of this type when creating a stub.
204      * @param superClass The super class of this type when creating a stub.
205      * @param interfaces The interfaces of this type when creating a stub.
206      */

207     JavaType(String typeName, int modifiers, TypeDescription.Generic superClass, TypeList.Generic interfaces) {
208         typeDescription = new TypeDescription.Latent(typeName, modifiers, superClass, interfaces);
209     }
210
211     /**
212      * Returns at least a stub representing this type where the stub does not define any methods or fields. If a type exists for
213      * the current runtime, a loaded type representation is returned.
214      *
215      * @return A type description for this Java type.
216      */

217     public TypeDescription getTypeStub() {
218         return typeDescription;
219     }
220
221     /**
222      * Loads the class that is represented by this Java type.
223      *
224      * @return A loaded type of this Java type.
225      * @throws ClassNotFoundException If the represented type cannot be loaded.
226      */

227     @CachedReturnPlugin.Enhance
228     public Class<?> load() throws ClassNotFoundException {
229         return Class.forName(typeDescription.getName(), false, ClassLoadingStrategy.BOOTSTRAP_LOADER);
230     }
231
232     /**
233      * Loads the class that is represented by this Java type and represents it as a {@link TypeDescription}.
234      *
235      * @return A loaded type of this Java type.
236      * @throws ClassNotFoundException If the represented type cannot be loaded.
237      */

238     public TypeDescription loadAsDescription() throws ClassNotFoundException {
239         return TypeDescription.ForLoadedType.of(load());
240     }
241
242     /**
243      * Returns {@code trueif this type is available on the current JVM.
244      *
245      * @return {@code trueif this type is available on the current JVM.
246      */

247     @CachedReturnPlugin.Enhance
248     public boolean isAvailable() {
249         try {
250             load();
251             return true;
252         } catch (ClassNotFoundException ignored) {
253             return false;
254         }
255     }
256
257     /**
258      * Checks if the supplied object is an instance of this type.
259      *
260      * @param instance The instance to check.
261      * @return {@code trueif the supplied object is an instance of this type.
262      */

263     public boolean isInstance(Object instance) {
264         if (!isAvailable()) {
265             return false;
266         }
267         try {
268             return load().isInstance(instance);
269         } catch (ClassNotFoundException ignored) {
270             return false;
271         }
272     }
273 }
274