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 /**
 27  * Base builder for attribute containing class file entities.
 28  *
 29  * @param <S> the type of the symbol representation
 30  * @param <T> the type of type descriptors representation
 31  * @param <E> the type of pool entries
 32  * @param <D> the type of this builder
 33  */
 34  public class AttributeBuilder<S, T, E, D extends AttributeBuilder<S, T, E, D>>
 35         extends AbstractBuilder<S, T, E, D> {
 36 
 37      /**
 38       * The number of attributes.
 39       */
 40     protected int nattrs;
 41 
 42     /**
 43      * The attributes represented as bytes.
 44      */
 45     protected GrowableByteBuffer attributes = new GrowableByteBuffer();
 46 
 47     /**
 48      * Create an attribute builder.
 49      *
 50      * @param poolHelper the helper to build the constant pool
 51      * @param typeHelper the helper to use to manipulate type descriptors
 52      */
 53     public AttributeBuilder(PoolHelper<S, T, E> poolHelper, TypeHelper<S, T> typeHelper) {
 54         super(poolHelper, typeHelper);
 55     }
 56 
 57     /**
 58      * Add a class file Attribute.  Defined as:
 59      * <pre>
 60      * {@code   attribute_info {
 61      *     u2 attribute_name_index;
 62      *     u4 attribute_length;
 63      *     u1 info[attribute_length];
 64      *   }}
 65      * </pre>
 66      *
 67      * @param name the attribute name
 68      * @param bytes the bytes of the attribute info
 69      * @return this builder, for chained calls
 70      */
 71     public D withAttribute(CharSequence name, byte[] bytes) {
 72         attributes.writeChar(poolHelper.putUtf8(name));
 73         attributes.writeInt(bytes.length);
 74         attributes.writeBytes(bytes);
 75         nattrs++;
 76         return thisBuilder();
 77     }
 78 
 79     /**
 80      * Add a class file Attribute, using a writer.  Defined as:
 81      * <pre>
 82      * {@code   attribute_info {
 83      *     u2 attribute_name_index;
 84      *     u4 attribute_length;
 85      *     u1 info[attribute_length];
 86      *   }}
 87      * </pre>
 88      *
 89      * @param <Z> the type of the object representing the attribute
 90      * @param name the attribute name
 91      * @param attr the representation of the attribute
 92      * @param attrWriter the writer which transform the attribute representation into bytes
 93      * @return this builder, for chained calls
 94      */
 95     public <Z> D withAttribute(CharSequence name, Z attr, AttributeWriter<S, T, E, Z> attrWriter) {
 96         attributes.writeChar(poolHelper.putUtf8(name));
 97         int offset = attributes.offset;
 98         attributes.writeInt(0);
 99         attrWriter.write(attr, poolHelper, attributes);
100         int len = attributes.offset - offset - 4;
101         attributes.withOffset(offset, buf -> buf.writeInt(len));
102         nattrs++;
103         return thisBuilder();
104     }
105 
106      /**
107       * Writer for transforming attribute representations to bytes
108       *
109       * @param <S> the type of symbol representation
110       * @param <T> the type of type descriptors representation
111       * @param <E> the type of pool entries
112       * @param <A> the type of the object representing the attribute
113       */
114     public interface AttributeWriter<S, T, E, A> {
115 
116         /**
117          * Write an attribute representation into a byte buffer.
118          *
119          * @param attr the representation of the attribute
120          * @param poolHelper the constant pool helper
121          * @param buf the buffer to collect the bytes
122          */
123         void write(A attr, PoolHelper<S, T, E> poolHelper, GrowableByteBuffer buf);
124     }
125 }