1 /* 2 * Copyright (c) 2019, 2020, 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 package org.openjdk.asmtools.jdis; 24 25 import org.openjdk.asmtools.jasm.JasmTokens; 26 import org.openjdk.asmtools.jasm.Tables; 27 28 import java.io.DataInputStream; 29 import java.io.IOException; 30 import java.util.ArrayList; 31 import java.util.List; 32 33 import static java.lang.String.format; 34 import static org.openjdk.asmtools.jasm.JasmTokens.Token.*; 35 import static org.openjdk.asmtools.jdis.TraceUtils.traceln; 36 37 /** 38 * The Record attribute data 39 * <p> 40 * since class file 58.65535 (JEP 359) 41 */ 42 public class RecordData extends Indenter { 43 44 45 private final ClassData cls; 46 private List<Component> components; 47 48 public RecordData(ClassData cls) { 49 this.cls = cls; 50 } 51 52 public RecordData read(DataInputStream in) throws IOException { 53 int count = in.readUnsignedShort(); 54 traceln("components=" + count); 55 components = new ArrayList<>(count); 56 for (int i = 0; i < count; i++) { 57 components.add(new Component(cls).read(in)); 58 } 59 return this; 60 } 61 62 /** 63 * Prints the record data to the current output stream. called from ClassData. 64 */ 65 public void print() throws IOException { 66 int count = components.size(); 67 if (count > 0) { 68 cls.out.println(getIndentString() + RECORD.parseKey() + getIndentString() + LBRACE.parseKey()); 69 for (int i = 0; i < count; i++) { 70 Component cn = components.get(i); 71 cn.setIndent(indent() * 2); 72 if (i != 0 && cn.getAnnotationsCount() > 0) 73 cn.out.println(); 74 cn.print(); 75 } 76 cls.out.println(getIndentString() + RBRACE.parseKey()); 77 cls.out.println(); 78 } 79 } 80 81 private class Component extends MemberData { 82 // CP index to the name 83 private int name_cpx; 84 // CP index to the type descriptor 85 private int type_cpx; 86 87 public Component(ClassData cls) { 88 super(cls); 89 memberType = "RecordData"; 90 } 91 92 @Override 93 protected boolean handleAttributes(DataInputStream in, Tables.AttrTag attrtag, int attrlen) throws IOException { 94 // Read the Attributes 95 boolean handled = true; 96 switch (attrtag) { 97 case ATT_Signature: 98 if( signature != null ) { 99 traceln("Record attribute: more than one attribute Signature are in component.attribute_info_attributes[attribute_count]"); 100 traceln("Last one will be used."); 101 } 102 signature = new SignatureData(cls).read(in, attrlen); 103 break; 104 default: 105 handled = false; 106 break; 107 } 108 return handled; 109 } 110 111 /** 112 * Read and resolve the component data called from ClassData. 113 */ 114 public Component read(DataInputStream in) throws IOException { 115 // read the Component CP indexes 116 name_cpx = in.readUnsignedShort(); 117 type_cpx = in.readUnsignedShort(); 118 traceln(2, "RecordComponent: name[" + name_cpx + "]=" + cls.pool.getString(name_cpx) 119 + " descriptor[" + type_cpx + "]=" + cls.pool.getString(type_cpx)); 120 // Read the attributes 121 readAttributes(in); 122 return this; 123 } 124 125 /** 126 * Prints the component data to the current output stream. called from RecordData. 127 */ 128 public void print() throws IOException { 129 // print component's attributes 130 super.printAnnotations(getIndentString()); 131 // print component 132 StringBuilder bodyPrefix = new StringBuilder(getIndentString()); 133 StringBuilder tailPrefix = new StringBuilder(); 134 if (isSynthetic) { 135 bodyPrefix.append(JasmTokens.Token.SYNTHETIC.parseKey()).append(' '); 136 } 137 if (isDeprecated) { 138 bodyPrefix.append(JasmTokens.Token.DEPRECATED.parseKey()).append(' '); 139 } 140 // component 141 bodyPrefix.append(JasmTokens.Token.COMPONENT.parseKey()).append(' '); 142 143 printVar(bodyPrefix, tailPrefix,name_cpx, type_cpx); 144 } 145 } 146 }