1515 */
1616package net .bytebuddy .utility ;
1717
18+ import codes .rafael .asmjdkbridge .JdkClassReader ;
19+ import net .bytebuddy .ClassFileVersion ;
20+ import net .bytebuddy .build .AccessControllerPlugin ;
1821import net .bytebuddy .utility .nullability .MaybeNull ;
22+ import net .bytebuddy .utility .privilege .GetSystemPropertyAction ;
1923import org .objectweb .asm .Attribute ;
2024import org .objectweb .asm .ClassReader ;
2125import org .objectweb .asm .ClassVisitor ;
2226
27+ import java .security .PrivilegedAction ;
28+
2329/**
2430 * A facade for creating a class reader that accepts {@link ClassVisitor} instances and reader flags.
2531 */
@@ -66,35 +72,121 @@ interface Factory {
6672 AsmClassReader make (byte [] binaryRepresentation , boolean experimental );
6773
6874 /**
69- * A default implementation that creates a pure ASM {@link ClassReader} .
75+ * Default implementations for factories of {@link AsmClassReader}s .
7076 */
7177 enum Default implements Factory {
7278
7379 /**
74- * The singleton instance.
80+ * Uses a processor as it is configured by {@link OpenedClassReader#PROCESSOR_PROPERTY},
81+ * or {@link AsmClassWriter.Factory.Default#ASM_FIRST} if no implicit processor is defined.
7582 */
76- INSTANCE ;
83+ IMPLICIT {
84+
85+ /**
86+ * {@inheritDoc}
87+ */
88+ public AsmClassReader make (byte [] binaryRepresentation , boolean experimental ) {
89+ return FACTORY .make (binaryRepresentation , experimental );
90+ }
91+ },
7792
7893 /**
79- * {@inheritDoc}
94+ * A factory for a class reader that uses ASM's internal implementation whenever possible.
8095 */
81- public AsmClassReader make (byte [] binaryRepresentation ) {
82- return new AsmClassReader .Default (OpenedClassReader .of (binaryRepresentation ));
96+ ASM_FIRST {
97+ /**
98+ * {@inheritDoc}
99+ */
100+ public AsmClassReader make (byte [] binaryRepresentation , boolean experimental ) {
101+ return ClassFileVersion .ofClassFile (binaryRepresentation ).isGreaterThan (ClassFileVersion .latest ())
102+ ? CLASS_FILE_API_ONLY .make (binaryRepresentation )
103+ : ASM_ONLY .make (binaryRepresentation );
104+ }
105+ },
106+
107+ /**
108+ * A factory for a class reader that uses the class file API whenever possible.
109+ */
110+ CLASS_FILE_API_FIRST {
111+ /**
112+ * {@inheritDoc}
113+ */
114+ public AsmClassReader make (byte [] binaryRepresentation , boolean experimental ) {
115+ return ClassFileVersion .ofThisVm ().isAtLeast (ClassFileVersion .JAVA_V24 )
116+ ? CLASS_FILE_API_ONLY .make (binaryRepresentation )
117+ : ASM_ONLY .make (binaryRepresentation );
118+ }
119+ },
120+
121+ /**
122+ * A factory for a class reader that always uses ASM's internal implementation.
123+ */
124+ ASM_ONLY {
125+ /**
126+ * {@inheritDoc}
127+ */
128+ public AsmClassReader make (byte [] binaryRepresentation , boolean experimental ) {
129+ return new ForAsm (OpenedClassReader .of (binaryRepresentation , experimental ));
130+ }
131+ },
132+
133+ /**
134+ * A factory for a class reader that always uses the class file API.
135+ */
136+ CLASS_FILE_API_ONLY {
137+
138+ /**
139+ * {@inheritDoc}
140+ */
141+ public AsmClassReader make (byte [] binaryRepresentation , boolean experimental ) {
142+ return new AsmClassReader .ForClassFileApi (new JdkClassReader (binaryRepresentation ));
143+ }
144+ };
145+
146+ /**
147+ * The implicit factory to use for writing class files.
148+ */
149+ private static final Factory FACTORY ;
150+
151+ /*
152+ * Resolves the implicit reader factory, if any.
153+ */
154+ static {
155+ String processor ;
156+ try {
157+ processor = doPrivileged (new GetSystemPropertyAction (OpenedClassReader .PROCESSOR_PROPERTY ));
158+ } catch (Throwable ignored ) {
159+ processor = null ;
160+ } // TODO: ASM_FIRST
161+ FACTORY = processor == null ? Default .CLASS_FILE_API_ONLY : Default .valueOf (processor );
162+ }
163+
164+ /**
165+ * A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
166+ *
167+ * @param action The action to execute from a privileged context.
168+ * @param <T> The type of the action's resolved value.
169+ * @return The action's resolved value.
170+ */
171+ @ MaybeNull
172+ @ AccessControllerPlugin .Enhance
173+ private static <T > T doPrivileged (PrivilegedAction <T > action ) {
174+ return action .run ();
83175 }
84176
85177 /**
86178 * {@inheritDoc}
87179 */
88- public AsmClassReader make (byte [] binaryRepresentation , boolean experimental ) {
89- return new AsmClassReader . Default ( OpenedClassReader . of ( binaryRepresentation , experimental ) );
180+ public AsmClassReader make (byte [] binaryRepresentation ) {
181+ return make ( binaryRepresentation , OpenedClassReader . EXPERIMENTAL );
90182 }
91183 }
92184 }
93185
94186 /**
95- * A class reader for ASM's default {@link ClassReader}.
187+ * A class reader for ASM's own {@link ClassReader}.
96188 */
97- class Default implements AsmClassReader {
189+ class ForAsm implements AsmClassReader {
98190
99191 /**
100192 * Indicates that no custom attributes should be mapped.
@@ -107,11 +199,11 @@ class Default implements AsmClassReader {
107199 private final ClassReader classReader ;
108200
109201 /**
110- * Creates a new default ASM class reader.
202+ * Creates a new ASM class reader that uses ASM's internal implementation .
111203 *
112204 * @param classReader The class reader that represents the class file to be read.
113205 */
114- public Default (ClassReader classReader ) {
206+ public ForAsm (ClassReader classReader ) {
115207 this .classReader = classReader ;
116208 }
117209
@@ -132,4 +224,39 @@ public void accept(ClassVisitor classVisitor, int flags) {
132224 classReader .accept (classVisitor , NO_ATTRIBUTES , flags );
133225 }
134226 }
227+
228+ /**
229+ * A class reader that is based upon the Class File API.
230+ */
231+ class ForClassFileApi implements AsmClassReader {
232+
233+ /**
234+ * The class reader that represents the class file to be read.
235+ */
236+ private final JdkClassReader classReader ;
237+
238+ /**
239+ * Creates a new class reader that is based upon the Class File API.
240+ *
241+ * @param classReader The class reader that represents the class file to be read.
242+ */
243+ public ForClassFileApi (JdkClassReader classReader ) {
244+ this .classReader = classReader ;
245+ }
246+
247+ /**
248+ * {@inheritDoc}
249+ */
250+ @ MaybeNull
251+ public <T > T unwrap (Class <T > type ) {
252+ return null ;
253+ }
254+
255+ /**
256+ * {@inheritDoc}
257+ */
258+ public void accept (ClassVisitor classVisitor , int flags ) {
259+ classReader .accept (classVisitor , flags );
260+ }
261+ }
135262}
0 commit comments