1 /*
  2  * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.reflect;
 27 
 28 import java.util.Collections;
 29 import java.util.Map;
 30 import java.util.Set;
 31 import static java.util.Map.entry;
 32 
 33 /**
 34  * Represents a JVM access or module-related flag on a runtime member,
 35  * such as a {@linkplain Class class}, {@linkplain Field field}, or
 36  * {@linkplain Executable method}.
 37  *
 38  * <P>JVM access and module-related flags are related to, but distinct
 39  * from Java language {@linkplain Modifier modifiers}. Some modifiers
 40  * and access flags have a one-to-one correspondence, such as {@code
 41  * public}. In other cases, some language-level modifiers do
 42  * <em>not</em> have an access flag, such as {@code sealed} (JVMS
 43  * {@jvms 4.7.31}) and some access flags have no corresponding
 44  * modifier, such as {@linkplain #SYNTHETIC synthetic}.
 45  *
 46  * <p>The values for the constants representing the access and module
 47  * flags are taken from sections of <cite>The Java Virtual Machine
 48  * Specification</cite> including {@jvms 4.1} (class access and
 49  * property modifiers), {@jvms 4.5} (field access and property flags),
 50  * {@jvms 4.6} (method access and property flags), {@jvms 4.7.6}
 51  * (nested class access and property flags), {@jvms 4.7.24} (method
 52  * parameters), and {@jvms 4.7.25} (module flags and requires,
 53  * exports, and opens flags).
 54  *
 55  * <p>The {@linkplain #mask() mask} values for the different access
 56  * flags are <em>not</em> distinct. Flags are defined for different
 57  * kinds of JVM structures and the same bit position has different
 58  * meanings in different contexts. For example, {@code 0x0000_0040}
 59  * indicates a {@link #VOLATILE volatile} field but a {@linkplain
 60  * #BRIDGE bridge method}; {@code 0x0000_0080} indicates a {@link
 61  * #TRANSIENT transient} field but a {@linkplain #VARARGS variable
 62  * arity (varargs)} method.
 63  *
 64  * <p>The access flag constants are ordered by non-decreasing mask
 65  * value; that is the mask value of a constant is greater than or
 66  * equal to the mask value of an immediate neighbor to its (syntactic)
 67  * left. If new constants are added, this property will be
 68  * maintained. That implies new constants will not necessarily be
 69  * added at the end of the existing list.
 70  *
 71  * @see java.lang.reflect.Modifier
 72  * @see java.lang.module.ModuleDescriptor.Modifier
 73  * @see java.lang.module.ModuleDescriptor.Requires.Modifier
 74  * @see java.lang.module.ModuleDescriptor.Exports.Modifier
 75  * @see java.lang.module.ModuleDescriptor.Opens.Modifier
 76  * @see java.compiler/javax.lang.model.element.Modifier
 77  * @since 20
 78  */
 79 @SuppressWarnings("doclint:reference") // cross-module link
 80 public enum AccessFlag {
 81     /**
 82      * The access flag {@code ACC_PUBLIC}, corresponding to the source
 83      * modifier {@link Modifier#PUBLIC public} with a mask value of
 84      * {@code 0x0001}.
 85      */
 86     PUBLIC(Modifier.PUBLIC, true,
 87            Set.of(Location.CLASS, Location.FIELD, Location.METHOD,
 88                   Location.INNER_CLASS)),
 89 
 90     /**
 91      * The access flag {@code ACC_PRIVATE}, corresponding to the
 92      * source modifier {@link Modifier#PRIVATE private} with a mask
 93      * value of {@code 0x0002}.
 94      */
 95     PRIVATE(Modifier.PRIVATE, true,
 96             Set.of(Location.FIELD, Location.METHOD, Location.INNER_CLASS)),
 97 
 98     /**
 99      * The access flag {@code ACC_PROTECTED}, corresponding to the
100      * source modifier {@link Modifier#PROTECTED protected} with a mask
101      * value of {@code 0x0004}.
102      */
103     PROTECTED(Modifier.PROTECTED, true,
104               Set.of(Location.FIELD, Location.METHOD, Location.INNER_CLASS)),
105 
106     /**
107      * The access flag {@code ACC_STATIC}, corresponding to the source
108      * modifier {@link Modifier#STATIC static} with a mask value of
109      * {@code 0x0008}.
110      */
111     STATIC(Modifier.STATIC, true,
112            Set.of(Location.FIELD, Location.METHOD, Location.INNER_CLASS)),
113 
114     /**
115      * The access flag {@code ACC_FINAL}, corresponding to the source
116      * modifier {@link Modifier#FINAL final} with a mask
117      * value of {@code 0x0010}.
118      */
119     FINAL(Modifier.FINAL, true,
120           Set.of(Location.CLASS, Location.FIELD, Location.METHOD,
121                  Location.INNER_CLASS, Location.METHOD_PARAMETER)),
122 
123     /**
124      * The access flag {@code ACC_SUPER} with a mask value of {@code
125      * 0x0020}.
126      */
127     SUPER(0x0000_0020, false, Set.of(Location.CLASS)),
128 
129     /**
130      * The module flag {@code ACC_OPEN} with a mask value of {@code
131      * 0x0020}.
132      * @see java.lang.module.ModuleDescriptor#isOpen
133      */
134     OPEN(0x0000_0020, false, Set.of(Location.MODULE)),
135 
136     /**
137      * The module requires flag {@code ACC_TRANSITIVE} with a mask
138      * value of {@code 0x0020}.
139      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#TRANSITIVE
140      */
141     TRANSITIVE(0x0000_0020, false, Set.of(Location.MODULE_REQUIRES)),
142 
143     /**
144      * The access flag {@code ACC_SYNCHRONIZED}, corresponding to the
145      * source modifier {@link Modifier#SYNCHRONIZED synchronized} with
146      * a mask value of {@code 0x0020}.
147      */
148     SYNCHRONIZED(Modifier.SYNCHRONIZED, true, Set.of(Location.METHOD)),
149 
150     /**
151      * The module requires flag {@code ACC_STATIC_PHASE} with a mask
152      * value of {@code 0x0040}.
153      * @see java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC
154      */
155     STATIC_PHASE(0x0000_0040, false, Set.of(Location.MODULE_REQUIRES)),
156 
157      /**
158       * The access flag {@code ACC_VOLATILE}, corresponding to the
159       * source modifier {@link Modifier#VOLATILE volatile} with a mask
160       * value of {@code 0x0040}.
161       */
162     VOLATILE(Modifier.VOLATILE, true, Set.of(Location.FIELD)),
163 
164     /**
165      * The access flag {@code ACC_BRIDGE} with a mask value of {@code
166      * 0x0040}.
167      * @see Method#isBridge()
168      */
169     BRIDGE(0x0000_0040, false, Set.of(Location.METHOD)),
170 
171     /**
172      * The access flag {@code ACC_TRANSIENT}, corresponding to the
173      * source modifier {@link Modifier#TRANSIENT transient} with a
174      * mask value of {@code 0x0080}.
175      */
176     TRANSIENT(Modifier.TRANSIENT, true, Set.of(Location.FIELD)),
177 
178     /**
179      * The access flag {@code ACC_VARARGS} with a mask value of {@code
180      * 0x0080}.
181      * @see Executable#isVarArgs()
182      */
183     VARARGS(0x0000_0080, false, Set.of(Location.METHOD)),
184 
185     /**
186      * The access flag {@code ACC_NATIVE}, corresponding to the source
187      * modifier {@link Modifier#NATIVE native} with a mask value of {@code
188      * 0x0100}.
189      */
190     NATIVE(Modifier.NATIVE, true, Set.of(Location.METHOD)),
191 
192     /**
193      * The access flag {@code ACC_INTERFACE} with a mask value of
194      * {@code 0x0200}.
195      * @see Class#isInterface()
196      */
197     INTERFACE(Modifier.INTERFACE, false,
198               Set.of(Location.CLASS, Location.INNER_CLASS)),
199 
200     /**
201      * The access flag {@code ACC_ABSTRACT}, corresponding to the
202      * source modifier {@link Modifier#ABSTRACT abstract} with a mask
203      * value of {@code 0x0400}.
204      */
205     ABSTRACT(Modifier.ABSTRACT, true,
206              Set.of(Location.CLASS, Location.METHOD, Location.INNER_CLASS)),
207 
208     /**
209      * The access flag {@code ACC_STRICT}, corresponding to the source
210      * modifier {@link Modifier#STRICT strictfp} with a mask value of
211      * {@code 0x0800}.
212      */
213     STRICT(Modifier.STRICT, true, Set.of(Location.METHOD)),
214 
215     /**
216      * The access flag {@code ACC_SYNTHETIC} with a mask value of
217      * {@code 0x1000}.
218      * @see Class#isSynthetic()
219      * @see Executable#isSynthetic()
220      * @see java.lang.module.ModuleDescriptor.Modifier#SYNTHETIC
221      */
222     SYNTHETIC(0x0000_1000, false,
223               Set.of(Location.CLASS, Location.FIELD, Location.METHOD,
224                      Location.INNER_CLASS, Location.METHOD_PARAMETER,
225                      Location.MODULE, Location.MODULE_REQUIRES,
226                      Location.MODULE_EXPORTS, Location.MODULE_OPENS)),
227 
228     /**
229      * The access flag {@code ACC_ANNOTATION} with a mask value of
230      * {@code 0x2000}.
231      * @see Class#isAnnotation()
232      */
233     ANNOTATION(0x0000_2000, false,
234                Set.of(Location.CLASS, Location.INNER_CLASS)),
235 
236     /**
237      * The access flag {@code ACC_ENUM} with a mask value of {@code
238      * 0x4000}.
239      * @see Class#isEnum()
240      */
241     ENUM(0x0000_4000, false,
242          Set.of(Location.CLASS, Location.FIELD, Location.INNER_CLASS)),
243 
244     /**
245      * The access flag {@code ACC_MANDATED} with a mask value of
246      * {@code 0x8000}.
247      */
248     MANDATED(0x0000_8000, false,
249              Set.of(Location.METHOD_PARAMETER,
250                     Location.MODULE, Location.MODULE_REQUIRES,
251                     Location.MODULE_EXPORTS, Location.MODULE_OPENS)),
252 
253     /**
254      * The access flag {@code ACC_MODULE} with a mask value of {@code
255      * 0x8000}.
256      */
257     MODULE(0x0000_8000, false, Set.of(Location.CLASS))
258     ;
259 
260     // May want to override toString for a different enum constant ->
261     // name mapping.
262 
263     private int mask;
264     private boolean sourceModifier;
265 
266     // Intentionally using Set rather than EnumSet since EnumSet is
267     // mutable.
268     private Set<Location> locations;
269 
270     private AccessFlag(int mask, boolean sourceModifier, Set<Location> locations) {
271         this.mask = mask;
272         this.sourceModifier = sourceModifier;
273         this.locations = locations;
274     }
275 
276     /**
277      * {@return the corresponding integer mask for the access flag}
278      */
279     public int mask() {
280         return mask;
281     }
282 
283     /**
284      * {@return whether or not the flag has a directly corresponding
285      * modifier in the Java programming language}
286      */
287     public boolean sourceModifier() {
288         return sourceModifier;
289     }
290 
291     /**
292      * {@return kinds of constructs the flag can be applied to}
293      */
294     public Set<Location> locations() {
295         return locations;
296     }
297 
298     /**
299      * {@return a set of access flags for the given mask value
300      * appropriate for the location in question}
301      *
302      * @param mask bit mask of access flags
303      * @param location context to interpret mask value
304      * @throws IllegalArgumentException if the mask contains bit
305      * positions not support for the location in question
306      */
307     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
308         Set<AccessFlag> result = java.util.EnumSet.noneOf(AccessFlag.class);
309         for (var accessFlag : LocationToFlags.locationToFlags.get(location)) {
310             int accessMask = accessFlag.mask();
311             if ((mask &  accessMask) != 0) {
312                 result.add(accessFlag);
313                 mask = mask & ~accessMask;
314             }
315         }
316         if (mask != 0) {
317             throw new IllegalArgumentException("Unmatched bit position 0x" +
318                                                Integer.toHexString(mask) +
319                                                " for location " + location);
320         }
321         return Collections.unmodifiableSet(result);
322     }
323 
324     /**
325      * A location within a class file where flags can be applied.
326      *
327      * Note that since these locations represent class file structures
328      * rather than language structures many language structures, such
329      * as constructors and interfaces, are <em>not</em> present.
330      * @since 20
331      */
332     public enum Location {
333         /**
334          * Class location.
335          * @jvms 4.1 The ClassFile Structure
336          */
337         CLASS,
338 
339         /**
340          * Field location.
341          * @jvms 4.5 Fields
342          */
343         FIELD,
344 
345         /**
346          * Method location.
347          * @jvms 4.6 Method
348          */
349         METHOD,
350 
351         /**
352          * Inner class location.
353          * @jvms 4.7.6 The InnerClasses Attribute
354          */
355         INNER_CLASS,
356 
357         /**
358          * Method parameter loccation.
359          * @jvms 4.7.24. The MethodParameters Attribute
360          */
361         METHOD_PARAMETER,
362 
363         /**
364          * Module location
365          * @jvms 4.7.25. The Module Attribute
366          */
367         MODULE,
368 
369         /**
370          * Module requires location
371          * @jvms 4.7.25. The Module Attribute
372          */
373         MODULE_REQUIRES,
374 
375         /**
376          * Module exports location
377          * @jvms 4.7.25. The Module Attribute
378          */
379         MODULE_EXPORTS,
380 
381         /**
382          * Module opens location
383          * @jvms 4.7.25. The Module Attribute
384          */
385         MODULE_OPENS;
386 
387     }
388 
389     private static class LocationToFlags {
390         private static Map<Location, Set<AccessFlag>> locationToFlags =
391             Map.ofEntries(entry(Location.CLASS,
392                                 Set.of(PUBLIC, FINAL, SUPER,
393                                        INTERFACE, ABSTRACT,
394                                        SYNTHETIC, ANNOTATION,
395                                        ENUM, AccessFlag.MODULE)),
396                           entry(Location.FIELD,
397                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
398                                        STATIC, FINAL, VOLATILE,
399                                        TRANSIENT, SYNTHETIC, ENUM)),
400                           entry(Location.METHOD,
401                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
402                                        STATIC, FINAL, SYNCHRONIZED,
403                                        BRIDGE, VARARGS, NATIVE,
404                                        ABSTRACT, STRICT, SYNTHETIC)),
405                           entry(Location.INNER_CLASS,
406                                 Set.of(PUBLIC, PRIVATE, PROTECTED,
407                                        STATIC, FINAL, INTERFACE, ABSTRACT,
408                                        SYNTHETIC, ANNOTATION, ENUM)),
409                           entry(Location.METHOD_PARAMETER,
410                                 Set.of(FINAL, SYNTHETIC, MANDATED)),
411                           entry(Location.MODULE,
412                                 Set.of(OPEN, SYNTHETIC, MANDATED)),
413                           entry(Location.MODULE_REQUIRES,
414                                 Set.of(TRANSITIVE, STATIC_PHASE, SYNTHETIC, MANDATED)),
415                           entry(Location.MODULE_EXPORTS,
416                                 Set.of(SYNTHETIC, MANDATED)),
417                           entry(Location.MODULE_OPENS,
418                                 Set.of(SYNTHETIC, MANDATED)));
419     }
420 }