1 /*
  2  * Copyright (c) 2026, 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 jdk.internal.reflect;
 27 
 28 import java.lang.reflect.AccessFlag;
 29 import java.lang.reflect.ClassFileFormatVersion;
 30 import java.util.Collections;
 31 import java.util.EnumSet;
 32 import java.util.Objects;
 33 import java.util.Set;
 34 
 35 import jdk.internal.vm.annotation.Stable;
 36 
 37 import static java.lang.classfile.ClassFile.*;
 38 import static java.lang.reflect.AccessFlag.*;
 39 
 40 /// Support for [AccessFlag] reflection for the preview VM features supported by
 41 /// the current Java SE release.
 42 ///
 43 /// These preview features appear when VM is running with --enable-preview, or
 44 /// in x.65535 class files.  Tools must handle x.65535 class files when their
 45 /// own VM is not running in preview, so this class may be used by tools when
 46 ///  preview features are not enabled,
 47 public final class PreviewAccessFlags {
 48 
 49     public static final @Stable AccessFlag[]
 50             CLASS_PREVIEW_FLAGS = AccessFlagSet.createDefinition(PUBLIC, FINAL, IDENTITY, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM, MODULE),
 51             FIELD_PREVIEW_FLAGS = AccessFlagSet.createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM, STRICT_INIT),
 52             INNER_CLASS_PREVIEW_FLAGS = AccessFlagSet.createDefinition(PUBLIC, PRIVATE, PROTECTED, IDENTITY, STATIC, FINAL, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM);
 53 
 54     /// Preview variant of [Location#flagsMask()].
 55     public static int flagsMask(Location location) {
 56         return switch (location) {
 57             case FIELD -> ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
 58                     ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
 59                     ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM | ACC_STRICT_INIT; // strict init
 60             case INNER_CLASS -> ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_IDENTITY |
 61                     ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
 62                     ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM; // identity
 63             default -> location.flagsMask();
 64         };
 65     }
 66 
 67     /// Preview variant of [AccessFlag#locations()].
 68     public static Set<Location> locations(AccessFlag flag) {
 69         return switch (flag) {
 70             case SUPER -> Set.of();
 71             case IDENTITY -> Set.of(Location.CLASS, Location.INNER_CLASS);
 72             case STRICT_INIT -> Set.of(Location.FIELD);
 73             default -> flag.locations();
 74         };
 75     }
 76 
 77     /// Preview variant of [AccessFlagSet#findDefinition].
 78     public static AccessFlag[] findDefinition(Location location) {
 79         return switch (location) {
 80             case CLASS -> CLASS_PREVIEW_FLAGS;
 81             case FIELD -> FIELD_PREVIEW_FLAGS;
 82             case INNER_CLASS -> INNER_CLASS_PREVIEW_FLAGS;
 83             default -> AccessFlagSet.findDefinition(location);
 84         };
 85     }
 86 
 87     /// Preview variant of [AccessFlag#maskToAccessFlags].
 88     /// The method body should be in parity.
 89     /// @throws IllegalArgumentException if there is unrecognized flag bit
 90     public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
 91         var definition = findDefinition(location);  // null checks location
 92         int unmatchedMask = mask & (~flagsMask(location));
 93         if (unmatchedMask != 0) {
 94             throw new IllegalArgumentException("Unmatched bit position 0x" +
 95                     Integer.toHexString(unmatchedMask) +
 96                     " for location " + location +
 97                     " for preview class files");
 98         }
 99         return AccessFlagSet.ofValidated(definition, mask);
100     }
101 
102     private PreviewAccessFlags() {
103     }
104 }