test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/ClassBuilder.java
changeset 48826 c4d9d1b08e2e
equal deleted inserted replaced
48825:ef8a98bc71f8 48826:c4d9d1b08e2e
       
     1 /*
       
     2  * Copyright (c) 2017, 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.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 package jdk.experimental.bytecode;
       
    25 
       
    26 import java.util.function.Consumer;
       
    27 
       
    28 /**
       
    29  * Base class builder. The base of higher level class builders.
       
    30  *
       
    31  * @param <S> the type of symbol representation
       
    32  * @param <T> the type of type descriptors representation
       
    33  * @param <C> the type of this builder
       
    34  */
       
    35 public class ClassBuilder<S, T, C extends ClassBuilder<S, T, C>>
       
    36         extends DeclBuilder<S, T, byte[], C> {
       
    37 
       
    38     /**
       
    39      * The helper to use to manipulate type descriptors.
       
    40      */
       
    41     protected TypeHelper<S, T> typeHelper;
       
    42 
       
    43     /**
       
    44      * The symbol for the class being built.
       
    45      */
       
    46     protected S thisClass;
       
    47 
       
    48     /**
       
    49      * The super-interfaces of the class being built..
       
    50      */
       
    51     protected GrowableByteBuffer interfaces = new GrowableByteBuffer();
       
    52 
       
    53     /**
       
    54      * The fields of the class being built.
       
    55      */
       
    56     protected GrowableByteBuffer fields = new GrowableByteBuffer();
       
    57 
       
    58     /**
       
    59      * The methods of the class being built.
       
    60      */
       
    61     protected GrowableByteBuffer methods = new GrowableByteBuffer();
       
    62 
       
    63     int majorVersion;
       
    64     int minorVersion;
       
    65     int flags;
       
    66     int superclass;
       
    67     int nmethods, nfields, ninterfaces;
       
    68 
       
    69     /**
       
    70      * Create a class builder.
       
    71      *
       
    72      * @param poolHelper the helper to build the constant pool
       
    73      * @param typeHelper the helper to use to manipulate type descriptors
       
    74      */
       
    75     public ClassBuilder(BytePoolHelper<S, T> poolHelper, TypeHelper<S, T> typeHelper) {
       
    76         super(poolHelper, typeHelper);
       
    77         this.typeHelper = typeHelper;
       
    78     }
       
    79 
       
    80     /**
       
    81      * Set the minor class file version.
       
    82      *
       
    83      * @param minorVersion the minor version number
       
    84      * @return this builder, for chained calls
       
    85      */
       
    86     public C withMinorVersion(int minorVersion) {
       
    87         this.minorVersion = minorVersion;
       
    88         return thisBuilder();
       
    89     }
       
    90 
       
    91     /**
       
    92      * Set the major class file version.
       
    93      *
       
    94      * @param majorVersion the major version number
       
    95      * @return this builder, for chained calls
       
    96      */
       
    97     public C withMajorVersion(int majorVersion) {
       
    98         this.majorVersion = majorVersion;
       
    99         return thisBuilder();
       
   100     }
       
   101 
       
   102     /**
       
   103      * Set the class symbol
       
   104      *
       
   105      * @param thisClass the class symbol
       
   106      * @return this builder, for chained calls
       
   107      */
       
   108     public C withThisClass(S thisClass) {
       
   109         this.thisClass = thisClass;
       
   110         return thisBuilder();
       
   111     }
       
   112 
       
   113     /**
       
   114      * Set the class access flags
       
   115      *
       
   116      * @param flags an array of {@code Flag}
       
   117      * @return this builder, for chained calls
       
   118      */
       
   119     @Override
       
   120     public C withFlags(Flag... flags) {
       
   121         for (Flag f : flags) {
       
   122             this.flags |= f.flag;
       
   123         }
       
   124         return thisBuilder();
       
   125     }
       
   126 
       
   127     /**
       
   128      * Set the superclass
       
   129      *
       
   130      * @param sup the superclass symbol
       
   131      * @return this builder, for chained calls
       
   132      */
       
   133     public C withSuperclass(S sup) {
       
   134         this.superclass = poolHelper.putClass(sup);
       
   135         return thisBuilder();
       
   136     }
       
   137 
       
   138     /**
       
   139      * Add a super interface.
       
   140      *
       
   141      * @param sup an interface symbol
       
   142      * @return this builder, for chained calls
       
   143      */
       
   144     public C withSuperinterface(S sup) {
       
   145         this.interfaces.writeChar(poolHelper.putClass(sup));
       
   146         ninterfaces++;
       
   147         return thisBuilder();
       
   148     }
       
   149 
       
   150     /**
       
   151      * Add a field.
       
   152      *
       
   153      * @param name the name of the field
       
   154      * @param type the type descriptor of the field
       
   155      * @return this builder, for chained calls
       
   156      */
       
   157     public final C withField(CharSequence name, T type) {
       
   158         return withField(name, type, FB -> {
       
   159         });
       
   160     }
       
   161 
       
   162     /**
       
   163      * Add a field.
       
   164      *
       
   165      * @param name the name of the field
       
   166      * @param type the type descriptor of the field
       
   167      * @param fieldConfig access to the {@code FieldBuilder} to allow clients to
       
   168      * adjust flags, annotations and bytecode attributes on the field declaration
       
   169      * @return this builder, for chained calls
       
   170      */
       
   171     public C withField(CharSequence name, T type, Consumer<? super FieldBuilder<S, T, byte[]>> fieldConfig) {
       
   172         FieldBuilder<S, T, byte[]> F = new FieldBuilder<>(name, type, poolHelper, typeHelper);
       
   173         fieldConfig.accept(F);
       
   174         F.build(fields);
       
   175         nfields++;
       
   176         return thisBuilder();
       
   177     }
       
   178 
       
   179     /**
       
   180      * Add a method
       
   181      *
       
   182      * @param name the name of the method
       
   183      * @param type the type descriptor of the method
       
   184      * @return this builder, for chained calls
       
   185      */
       
   186     public final C withMethod(CharSequence name, T type) {
       
   187         return withMethod(name, type, MB -> {
       
   188         });
       
   189     }
       
   190 
       
   191     /**
       
   192      * Add a method
       
   193      *
       
   194      * @param name the name of the method
       
   195      * @param type the type descriptor of the method
       
   196      * @param methodConfig access to the {@code MethodBuilder} to allow clients to
       
   197      * adjust flags, annotations and bytecode attributes on the method declaration
       
   198      * @return this builder, for chained calls
       
   199      */
       
   200     public C withMethod(CharSequence name, T type, Consumer<? super MethodBuilder<S, T, byte[]>> methodConfig) {
       
   201         MethodBuilder<S, T, byte[]> M = new MethodBuilder<>(thisClass, name, type, poolHelper, typeHelper);
       
   202         methodConfig.accept(M);
       
   203         M.build(methods);
       
   204         nmethods++;
       
   205         return thisBuilder();
       
   206     }
       
   207 
       
   208     /**
       
   209      * Build the constant pool into a byte array.
       
   210      *
       
   211      * @return a representation of this constant pool as a byte array
       
   212      */
       
   213     @SuppressWarnings("unchecked")
       
   214     public byte[] build() {
       
   215         ((BytePoolHelper<S, T>)poolHelper).addAttributes(this);
       
   216         addAnnotations();
       
   217         int thisClassIdx = poolHelper.putClass(thisClass);
       
   218         byte[] poolBytes = poolHelper.entries();
       
   219         GrowableByteBuffer buf = new GrowableByteBuffer();
       
   220         buf.writeInt(0xCAFEBABE);
       
   221         buf.writeChar(minorVersion);
       
   222         buf.writeChar(majorVersion);
       
   223         buf.writeChar(poolHelper.size() + 1);
       
   224         buf.writeBytes(poolBytes);
       
   225         buf.writeChar(flags);
       
   226         buf.writeChar(thisClassIdx);
       
   227         buf.writeChar(superclass);
       
   228         buf.writeChar(ninterfaces);
       
   229         if (ninterfaces > 0) {
       
   230             buf.writeBytes(interfaces);
       
   231         }
       
   232         buf.writeChar(nfields);
       
   233         buf.writeBytes(fields);
       
   234         buf.writeChar(nmethods);
       
   235         buf.writeBytes(methods);
       
   236         buf.writeChar(nattrs);
       
   237         buf.writeBytes(attributes);
       
   238         return buf.bytes();
       
   239     }
       
   240 }