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 }