1 /*
  2  * Copyright (c) 2024, 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 package java.lang.classfile.attribute;
 26 
 27 import java.lang.classfile.Attribute;
 28 import java.lang.classfile.AttributeMapper;
 29 import java.lang.classfile.Attributes;
 30 import java.lang.classfile.ClassElement;
 31 import java.lang.classfile.constantpool.Utf8Entry;
 32 import java.lang.constant.ClassDesc;
 33 import java.util.Arrays;
 34 import java.util.List;
 35 
 36 import jdk.internal.classfile.impl.BoundAttribute;
 37 import jdk.internal.classfile.impl.UnboundAttribute;
 38 import jdk.internal.classfile.impl.Util;
 39 import jdk.internal.javac.PreviewFeature;
 40 
 41 /**
 42  * Models the {@link Attributes#loadableDescriptors() LoadableDescriptors}
 43  * attribute (JVMS {@jvms value-objects-4.7.32}), which permits the JVM to
 44  * load mentioned classes and interfaces before the {@code class} file carrying
 45  * this attribute is loaded.
 46  * <p>
 47  * This attribute only appears on classes, and does not permit {@linkplain
 48  * AttributeMapper#allowMultiple multiple instances} in a class.  It has a
 49  * data dependency on the {@linkplain AttributeMapper.AttributeStability#CP_REFS
 50  * constant pool}.
 51  * <p>
 52  * The attribute is a preview VM feature in the current Java SE release.
 53  *
 54  * @see Attributes#loadableDescriptors()
 55  * @jvms value-objects-4.7.32 The {@code LoadableDescriptors} Attribute
 56  * @since 28
 57  */
 58 @PreviewFeature(feature = PreviewFeature.Feature.VALUE_OBJECTS, reflective = true)
 59 public sealed interface LoadableDescriptorsAttribute
 60         extends Attribute<LoadableDescriptorsAttribute>, ClassElement
 61         permits BoundAttribute.BoundLoadableDescriptorsAttribute, UnboundAttribute.UnboundLoadableDescriptorsAttribute {
 62 
 63     /**
 64      * {@return the list of loadable descriptors}
 65      */
 66     List<Utf8Entry> loadableDescriptors();
 67 
 68     /**
 69      * {@return the list of loadable descriptors, as nominal descriptors}
 70      */
 71     default List<ClassDesc> loadableDescriptorSymbols() {
 72         return Util.mappedList(loadableDescriptors(), Util::fieldTypeSymbol);
 73     }
 74 
 75     /**
 76      * {@return a {@code LoadableDescriptors} attribute}
 77      * @param loadableDescriptors the loadable descriptors
 78      * @throws IllegalArgumentException if the number of loadable descriptors
 79      *         exceeds the limit of {@link java.lang.classfile##u2 u2}
 80      */
 81     static LoadableDescriptorsAttribute of(List<Utf8Entry> loadableDescriptors) {
 82         return new UnboundAttribute.UnboundLoadableDescriptorsAttribute(loadableDescriptors);
 83     }
 84 
 85     /**
 86      * {@return a {@code LoadableDescriptors} attribute}
 87      * @param loadableDescriptors the loadable descriptors
 88      * @throws IllegalArgumentException if the number of loadable descriptors
 89      *         exceeds the limit of {@link java.lang.classfile##u2 u2}
 90      */
 91     static LoadableDescriptorsAttribute of(Utf8Entry... loadableDescriptors) {
 92         return of(List.of(loadableDescriptors));
 93     }
 94 
 95     /**
 96      * {@return a {@code LoadableDescriptors} attribute}
 97      * @param loadableDescriptors the loadable descriptors
 98      * @throws IllegalArgumentException if the number of loadable descriptors
 99      *         exceeds the limit of {@link java.lang.classfile##u2 u2}
100      */
101     static LoadableDescriptorsAttribute ofSymbols(List<ClassDesc> loadableDescriptors) {
102         return of(Util.fieldDescriptorList(loadableDescriptors));
103     }
104 
105     /**
106      * {@return a {@code LoadableDescriptors} attribute}
107      * @param loadableDescriptors the loadable descriptors
108      * @throws IllegalArgumentException if the number of loadable descriptors
109      *         exceeds the limit of {@link java.lang.classfile##u2 u2}
110      */
111     static LoadableDescriptorsAttribute ofSymbols(ClassDesc... loadableDescriptors) {
112         return ofSymbols(Arrays.asList(loadableDescriptors));
113     }
114 }