• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

raphw / byte-buddy / #730

28 Jan 2025 04:19PM UTC coverage: 85.352% (-0.02%) from 85.372%
#730

push

raphw
Adjust abstraction.

4 of 6 new or added lines in 2 files covered. (66.67%)

158 existing lines in 3 files now uncovered.

28977 of 33950 relevant lines covered (85.35%)

0.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.81
/byte-buddy-dep/src/main/java/net/bytebuddy/utility/AsmClassReader.java
1
/*
2
 * Copyright 2014 - Present 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.ClassFileVersion;
19
import net.bytebuddy.build.AccessControllerPlugin;
20
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
21
import net.bytebuddy.utility.dispatcher.JavaDispatcher;
22
import net.bytebuddy.utility.nullability.MaybeNull;
23
import net.bytebuddy.utility.privilege.GetSystemPropertyAction;
24
import org.objectweb.asm.Attribute;
25
import org.objectweb.asm.ClassReader;
26
import org.objectweb.asm.ClassVisitor;
27

28
import java.security.PrivilegedAction;
29

30
/**
31
 * A facade for creating a class reader that accepts {@link ClassVisitor} instances and reader flags.
32
 */
33
public interface AsmClassReader {
34

35
    /**
36
     * Indicates that no custom attributes should be mapped.
37
     */
38
    Attribute[] NO_ATTRIBUTES = new Attribute[0];
1✔
39

40
    /**
41
     * Unwraps a class reader to the underlying reader mechanism.
42
     *
43
     * @param type The type of the reader that should be unwrapped.
44
     * @param <T>  The type to unwrap.
45
     * @return The unwrapped instance or {@code null} if the underlying instance does not represent this type.
46
     */
47
    @MaybeNull
48
    <T> T unwrap(Class<T> type);
49

50
    /**
51
     * Accepts a class visitor to read a class.
52
     *
53
     * @param classVisitor The class visitor who should be used as a callback for a class file.
54
     * @param flags        The flags to consider while reading a class.
55
     */
56
    void accept(ClassVisitor classVisitor, int flags);
57

58
    /**
59
     * A factory to create a {@link AsmClassReader}.
60
     */
61
    interface Factory {
62

63
        /**
64
         * Creates a class reader for a given class file.
65
         *
66
         * @param binaryRepresentation The class file's binary representation.
67
         * @return A class reader representation for the supplied class file.
68
         */
69
        AsmClassReader make(byte[] binaryRepresentation);
70

71
        /**
72
         * Creates a class reader for a given class file.
73
         *
74
         * @param binaryRepresentation The class file's binary representation.
75
         * @param experimental         {@code true} if unknown Java class files versions should also be considered.
76
         * @return A class reader representation for the supplied class file.
77
         */
78
        AsmClassReader make(byte[] binaryRepresentation, boolean experimental);
79

80
        /**
81
         * Default implementations for factories of {@link AsmClassReader}s.
82
         */
83
        enum Default implements Factory {
1✔
84

85
            /**
86
             * Uses a processor as it is configured by {@link OpenedClassReader#PROCESSOR_PROPERTY},
87
             * or {@link AsmClassWriter.Factory.Default#ASM_FIRST} if no implicit processor is defined.
88
             */
89
            IMPLICIT {
1✔
90
                /**
91
                 * {@inheritDoc}
92
                 */
93
                public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
94
                    return (FACTORY == IMPLICIT ? ASM_FIRST : FACTORY).make(binaryRepresentation, experimental);
1✔
95
                }
96
            },
97

98
            /**
99
             * A factory for a class reader that uses ASM's internal implementation whenever possible.
100
             */
101
            ASM_FIRST {
1✔
102
                /**
103
                 * {@inheritDoc}
104
                 */
105
                public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
106
                    return ClassFileVersion.ofThisVm().isGreaterThan(ClassFileVersion.latest())
1✔
107
                            ? CLASS_FILE_API_ONLY.make(binaryRepresentation, experimental)
1✔
108
                            : ASM_ONLY.make(binaryRepresentation, experimental);
1✔
109
                }
110
            },
111

112
            /**
113
             * A factory for a class reader that uses the class file API whenever possible.
114
             */
115
            CLASS_FILE_API_FIRST {
1✔
116
                /**
117
                 * {@inheritDoc}
118
                 */
119
                public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
UNCOV
120
                    return ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V24)
×
NEW
121
                            ? CLASS_FILE_API_ONLY.make(binaryRepresentation, experimental)
×
NEW
122
                            : ASM_ONLY.make(binaryRepresentation, experimental);
×
123
                }
124
            },
125

126
            /**
127
             * A factory for a class reader that always uses ASM's internal implementation.
128
             */
129
            ASM_ONLY {
1✔
130
                /**
131
                 * {@inheritDoc}
132
                 */
133
                public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
134
                    return new ForAsm(OpenedClassReader.of(binaryRepresentation, experimental));
1✔
135
                }
136
            },
137

138
            /**
139
             * A factory for a class reader that always uses the class file API.
140
             */
141
            CLASS_FILE_API_ONLY {
1✔
142
                /**
143
                 * {@inheritDoc}
144
                 */
145
                public AsmClassReader make(byte[] binaryRepresentation, boolean experimental) {
UNCOV
146
                    return new AsmClassReader.ForClassFileApi(ForClassFileApi.DISPATCHER.make(
×
147
                            binaryRepresentation,
148
                            NO_ATTRIBUTES));
149
                }
150
            };
151

152
            /**
153
             * The implicit factory to use for writing class files.
154
             */
155
            private static final Factory FACTORY;
156

157
            /*
158
             * Resolves the implicit reader factory, if any.
159
             */
160
            static {
161
                String processor;
162
                try {
163
                    processor = doPrivileged(new GetSystemPropertyAction(OpenedClassReader.PROCESSOR_PROPERTY));
1✔
UNCOV
164
                } catch (Throwable ignored) {
×
UNCOV
165
                    processor = null;
×
166
                }
1✔
167
                FACTORY = processor == null ? Default.ASM_FIRST : Default.valueOf(processor);
1✔
168
            }
1✔
169

170
            /**
171
             * A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
172
             *
173
             * @param action The action to execute from a privileged context.
174
             * @param <T>    The type of the action's resolved value.
175
             * @return The action's resolved value.
176
             */
177
            @MaybeNull
178
            @AccessControllerPlugin.Enhance
179
            private static <T> T doPrivileged(PrivilegedAction<T> action) {
UNCOV
180
                return action.run();
×
181
            }
182

183
            /**
184
             * {@inheritDoc}
185
             */
186
            public AsmClassReader make(byte[] binaryRepresentation) {
187
                return make(binaryRepresentation, OpenedClassReader.EXPERIMENTAL);
1✔
188
            }
189
        }
190
    }
191

192
    /**
193
     * A class reader for ASM's own {@link ClassReader}.
194
     */
195
    class ForAsm implements AsmClassReader {
196

197
        /**
198
         * The class reader that represents the class file to be read.
199
         */
200
        private final ClassReader classReader;
201

202
        /**
203
         * Creates a new ASM class reader that uses ASM's internal implementation.
204
         *
205
         * @param classReader The class reader that represents the class file to be read.
206
         */
207
        public ForAsm(ClassReader classReader) {
1✔
208
            this.classReader = classReader;
1✔
209
        }
1✔
210

211
        /**
212
         * {@inheritDoc}
213
         */
214
        @MaybeNull
215
        public <T> T unwrap(Class<T> type) {
216
            return type.isInstance(classReader)
1✔
217
                    ? type.cast(classReader)
1✔
218
                    : null;
219
        }
220

221
        /**
222
         * {@inheritDoc}
223
         */
224
        public void accept(ClassVisitor classVisitor, int flags) {
225
            classReader.accept(classVisitor, NO_ATTRIBUTES, flags);
1✔
226
        }
1✔
227
    }
228

229
    /**
230
     * A class reader that is based upon the Class File API.
231
     */
232
    @HashCodeAndEqualsPlugin.Enhance
233
    class ForClassFileApi implements AsmClassReader {
234

235
        /**
236
         * A dispatcher to interact with {@code codes.rafael.asmjdkbridge.JdkClassReader}.
237
         */
238
        protected static final JdkClassReader DISPATCHER = doPrivileged(JavaDispatcher.of(
×
239
                JdkClassReader.class,
UNCOV
240
                ForClassFileApi.class.getClassLoader()));
×
241

242
        /**
243
         * The class reader that represents the class file to be read.
244
         */
245
        private final Object classReader;
246

247
        /**
248
         * Creates a new class reader that is based upon the Class File API.
249
         *
250
         * @param classReader The class reader that represents the class file to be read.
251
         */
UNCOV
252
        public ForClassFileApi(Object classReader) {
×
UNCOV
253
            if (!DISPATCHER.isInstance(classReader)) {
×
UNCOV
254
                throw new IllegalArgumentException();
×
255
            }
UNCOV
256
            this.classReader = classReader;
×
257
        }
×
258

259
        /**
260
         * A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
261
         *
262
         * @param action The action to execute from a privileged context.
263
         * @param <T>    The type of the action's resolved value.
264
         * @return The action's resolved value.
265
         */
266
        @AccessControllerPlugin.Enhance
267
        private static <T> T doPrivileged(PrivilegedAction<T> action) {
UNCOV
268
            return action.run();
×
269
        }
270

271
        /**
272
         * {@inheritDoc}
273
         */
274
        @MaybeNull
275
        public <T> T unwrap(Class<T> type) {
UNCOV
276
            return type.isInstance(classReader)
×
UNCOV
277
                    ? type.cast(classReader)
×
278
                    : null;
279
        }
280

281
        /**
282
         * {@inheritDoc}
283
         */
284
        public void accept(ClassVisitor classVisitor, int flags) {
UNCOV
285
            DISPATCHER.accept(classReader, classVisitor, flags);
×
UNCOV
286
        }
×
287

288
        /**
289
         * A dispatcher to interact with {@code codes.rafael.asmjdkbridge.JdkClassReader}.
290
         */
291
        @JavaDispatcher.Proxied("codes.rafael.asmjdkbridge.JdkClassReader")
292
        protected interface JdkClassReader {
293

294
            /**
295
             * Checks if the supplied object is an instance of {@code codes.rafael.asmjdkbridge.JdkClassReader}.
296
             *
297
             * @param value The instance to evaluate.
298
             * @return {@code true} if the supplied object is an instance of {@code codes.rafael.asmjdkbridge.JdkClassReader}.
299
             */
300
            @JavaDispatcher.Instance
301
            boolean isInstance(Object value);
302

303
            /**
304
             * Creates an instance of {@code codes.rafael.asmjdkbridge.JdkClassReader}.
305
             *
306
             * @param binaryRepresentation The binary representation of a class file to represent through the reader.
307
             * @param attribute            An array of attribute prototypes.
308
             * @return A new instance of {@code codes.rafael.asmjdkbridge.JdkClassReader}.
309
             */
310
            @JavaDispatcher.IsConstructor
311
            Object make(byte[] binaryRepresentation, Attribute[] attribute);
312

313
            /**
314
             * Accepts a class reader to visit the represented class file.
315
             *
316
             * @param classReader  The class reader that is being visited.
317
             * @param classVisitor The class visitor to visit the class.
318
             * @param flags        The flags to consider during reading.
319
             */
320
            void accept(Object classReader, ClassVisitor classVisitor, int flags);
321
        }
322
    }
323
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc