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 }