1 /*
  2  * Copyright (c) 1996, 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.Tables;
 26 import java.io.DataInputStream;
 27 import java.io.IOException;
 28 import java.io.PrintWriter;
 29 import java.util.ArrayList;
 30 
 31 import static java.lang.String.format;
 32 
 33 /**
 34  * Base class for ClassData, MethodData, FieldData and RecordData(JEP 360)
 35  */
 36 public abstract class MemberData extends Indenter {
 37 
 38     // access flags (modifiers)
 39     protected int access;
 40 
 41     // flags
 42     protected boolean isSynthetic = false;
 43     protected boolean isDeprecated = false;
 44 
 45     // Signature can be located in ClassFile, field_info, method_info, and component_info
 46     protected SignatureData signature;
 47 
 48     /**
 49      * The visible annotations for this class, member( field or method) or record component
 50      */
 51     protected ArrayList<AnnotationData> visibleAnnotations;
 52 
 53     /**
 54      * The invisible annotations for this class, member( field or method) or record component
 55      */
 56     protected ArrayList<AnnotationData> invisibleAnnotations;
 57 
 58     /**
 59      * The visible annotations for this class, member( field or method) or record component
 60      */
 61     protected ArrayList<TypeAnnotationData> visibleTypeAnnotations;
 62 
 63     /**
 64      * The invisible annotations for this class, member( field or method) or record component
 65      */
 66     protected ArrayList<TypeAnnotationData> invisibleTypeAnnotations;
 67 
 68     /**
 69      * The remaining attributes of this class, member( field or method) or record component
 70      */
 71     protected ArrayList<AttrData> attrs;
 72 
 73     // internal references
 74     protected final Options options = Options.OptionObject();
 75     protected final  boolean pr_cpx = options.contains(Options.PR.CPX);;
 76     protected ClassData cls;
 77     protected PrintWriter out;
 78     protected String memberType = "";
 79 
 80     public MemberData(ClassData cls) {
 81         this();
 82         init(cls);
 83     }
 84 
 85     public MemberData() {
 86     }
 87 
 88     public void init(ClassData cls) {
 89         this.out = cls.out;
 90         this.cls = cls;
 91     }
 92 
 93     protected boolean handleAttributes(DataInputStream in, Tables.AttrTag attrtag, int attrlen) throws IOException {
 94         // sub-classes override
 95         return false;
 96     }
 97 
 98     protected abstract void print() throws IOException;
 99 
100     final protected int getAnnotationsCount() {
101         return  ((visibleAnnotations == null) ? 0 : visibleAnnotations.size()) +
102                 ((invisibleAnnotations == null) ? 0 : invisibleAnnotations.size()) +
103                 ((visibleTypeAnnotations == null) ? 0 : visibleTypeAnnotations.size()) +
104                 ((invisibleTypeAnnotations == null) ? 0 : invisibleTypeAnnotations.size());
105 
106     }
107 
108     final protected void printAnnotations(String initialTab) {
109         if( getAnnotationsCount() > 0 ) {
110             if (visibleAnnotations != null) {
111                 for (AnnotationData visad : visibleAnnotations) {
112                     // out.print(initialTab);
113                     visad.print(out, initialTab);
114                     out.println();
115                 }
116             }
117             if (invisibleAnnotations != null) {
118                 for (AnnotationData invisad : invisibleAnnotations) {
119                     invisad.print(out, initialTab);
120                     out.println();
121                 }
122             }
123 
124             if (visibleTypeAnnotations != null) {
125                 for (TypeAnnotationData visad : visibleTypeAnnotations) {
126                     visad.print(out, initialTab);
127                     out.println();
128                 }
129             }
130             if (invisibleTypeAnnotations != null) {
131                 for (TypeAnnotationData invisad : invisibleTypeAnnotations) {
132                     invisad.print(out, initialTab);
133                     out.println();
134                 }
135             }
136         }
137     }
138 
139     protected void printVar(StringBuilder bodyPrefix, StringBuilder tailPrefix, int name_cpx, int type_cpx) {
140         if( pr_cpx ) {
141             bodyPrefix.append('#').append(name_cpx).append(":#").append(type_cpx);
142             tailPrefix.append(";\t // ").append(cls.pool.getName(name_cpx)).append(':').append(cls.pool.getName(type_cpx));
143 
144         } else {
145             bodyPrefix.append(cls.pool.getName(name_cpx)).append(':').append(cls.pool.getName(type_cpx));
146             tailPrefix.append(';');
147         }
148 
149         if (signature != null) {
150             signature.print(bodyPrefix.append(':').toString(), tailPrefix.append( pr_cpx ? ":" : "" ).toString());
151         } else {
152             out.print(bodyPrefix);
153             out.print(tailPrefix);
154         }
155         out.println();
156     }
157 
158     protected void readAttributes(DataInputStream in) throws IOException {
159         // Read the Attributes
160         int natt = in.readUnsignedShort();
161         attrs = new ArrayList<>(natt);
162         TraceUtils.traceln(format("%s - Attributes[%d]", memberType , natt));
163         AttrData attr;
164         for (int k = 0; k < natt; k++) {
165             int name_cpx = in.readUnsignedShort();
166             attr = new AttrData(cls);
167             attrs.add(attr);
168             String attr_name = cls.pool.getString(name_cpx);
169             TraceUtils.traceln(format("   #%d name[%d]=\"%s\"", k, name_cpx, attr_name));
170             Tables.AttrTag tag = Tables.attrtag(attr_name);
171             int attrlen = in.readInt();
172             switch (tag) {
173                 case ATT_Synthetic:
174                     // Read Synthetic Attr
175                     if (attrlen != 0) {
176                         throw new ClassFormatError("invalid Synthetic attr length");
177                     }
178                     isSynthetic = true;
179                     break;
180                 case ATT_Deprecated:
181                     // Read Deprecated Attr
182                     if (attrlen != 0) {
183                         throw new ClassFormatError("invalid Deprecated attr length");
184                     }
185                     isDeprecated = true;
186                     break;
187                 case ATT_RuntimeVisibleAnnotations:
188                 case ATT_RuntimeInvisibleAnnotations:
189                     // Read Annotations Attr
190                     int cnt = in.readShort();
191                     ArrayList<AnnotationData> annots = new ArrayList<>(cnt);
192                     boolean invisible = (tag == Tables.AttrTag.ATT_RuntimeInvisibleAnnotations);
193                     for (int i = 0; i < cnt; i++) {
194                         TraceUtils.traceln("      AnnotationData: #" + i);
195                         AnnotationData annot = new AnnotationData(invisible, cls);
196                         annot.read(in);
197                         annots.add(annot);
198                     }
199 
200                     if (invisible) {
201                         invisibleAnnotations = annots;
202                     } else {
203                         visibleAnnotations = annots;
204                     }
205                     break;
206                 case ATT_RuntimeVisibleTypeAnnotations:
207                 case ATT_RuntimeInvisibleTypeAnnotations:
208                     // Read Type Annotations Attr
209                     int tcnt = in.readShort();
210                     ArrayList<TypeAnnotationData> tannots = new ArrayList<>(tcnt);
211                     boolean tinvisible = (tag == Tables.AttrTag.ATT_RuntimeInvisibleTypeAnnotations);
212                     for (int tindex = 0; tindex < tcnt; tindex++) {
213                         TraceUtils.traceln("      TypeAnnotationData: #" + tindex);
214                         TypeAnnotationData tannot = new TypeAnnotationData(tinvisible, cls);
215                         tannot.read(in);
216                         tannots.add(tannot);
217                     }
218 
219                     if (tinvisible) {
220                         invisibleTypeAnnotations = tannots;
221                     } else {
222                         visibleTypeAnnotations = tannots;
223                     }
224                     break;
225                 default:
226                     boolean handled = handleAttributes(in, tag, attrlen);
227                     if (!handled) {
228                         attr.read(name_cpx, attrlen, in);
229                     }
230                     break;
231 
232             }
233         }
234     }
235 }