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 java.io.DataInputStream;
 26 import java.io.IOException;
 27 import java.io.PrintWriter;
 28 import java.util.ArrayList;
 29 
 30 import static java.lang.String.format;
 31 
 32 /**
 33  *
 34  */
 35 public class  AnnotationData {
 36     /*-------------------------------------------------------- */
 37     /* AnnotData Fields */
 38 
 39     protected String visAnnotToken = "@+";
 40     protected String invAnnotToken = "@-";
 41     protected String dataName = "AnnotationData";
 42     private boolean invisible = false;
 43     private int type_cpx = 0;  //an index into the constant pool indicating the annotation type for this annotation.
 44     private ArrayList<AnnotationElement> array = new ArrayList<>();
 45     private ClassData cls;
 46     /*-------------------------------------------------------- */
 47 
 48     public AnnotationData(boolean invisible, ClassData cls) {
 49         this.cls = cls;
 50         this.invisible = invisible;
 51     }
 52 
 53     public void read(DataInputStream in) throws IOException {
 54         type_cpx = in.readShort();
 55         int elemValueLength = in.readShort();
 56         TraceUtils.traceln(3, format(" %s: name[%d]=%s", dataName, type_cpx, cls.pool.getString(type_cpx)),
 57                 format(" %s: %s  num_elems: %d", dataName, cls.pool.getString(type_cpx), elemValueLength));
 58         for (int evc = 0; evc < elemValueLength; evc++) {
 59             AnnotationElement elem = new AnnotationElement(cls);
 60             TraceUtils.traceln(3, format(" %s: %s reading [%d]", dataName, cls.pool.getString(type_cpx), evc));
 61             elem.read(in, invisible);
 62             array.add(elem);
 63         }
 64     }
 65 
 66     public void print(PrintWriter out, String tab) {
 67         printHeader(out, tab);
 68         printBody(out, "");
 69     }
 70 
 71     protected void printHeader(PrintWriter out, String tab) {
 72         //Print annotation Header, which consists of the
 73         // Annotation Token ('@'), visibility ('+', '-'),
 74         // and the annotation name (type index, CPX).
 75 
 76         // Mark whether it is invisible or not.
 77         if (invisible) {
 78             out.print(tab + invAnnotToken);
 79         } else {
 80             out.print(tab + visAnnotToken);
 81         }
 82         String annoName = cls.pool.getString(type_cpx);
 83 
 84         // converts class type to java class name
 85         if (annoName.startsWith("L") && annoName.endsWith(";")) {
 86             annoName = annoName.substring(1, annoName.length() - 1);
 87         }
 88 
 89         out.print(annoName);
 90     }
 91 
 92     protected void printBody(PrintWriter out, String tab) {
 93         // For a standard annotation, print out brackets,
 94         // and list the name/value pairs.
 95         out.print(" { ");
 96         int i = 0;
 97         for (AnnotationElement elem : array) {
 98             elem.print(out, tab);
 99             if (i++ < array.size() - 1) {
100                 out.print(", ");
101             }
102         }
103         out.print("  }");
104     }
105 
106     @Override
107     public String toString() {
108         StringBuilder sb = new StringBuilder();
109         String annoName = cls.pool.getString(type_cpx);
110 
111         // converts class type to java class name
112         if (annoName.startsWith("L") && annoName.endsWith(";")) {
113             annoName = annoName.substring(1, annoName.length() - 1);
114         }
115 
116         //Print annotation
117         // Mark whether it is invisible or not.
118         if (invisible) {
119             sb.append(invAnnotToken);
120         } else {
121             sb.append(visAnnotToken);
122         }
123 
124         sb.append(annoName);
125         sb.append(" { ");
126 
127         int i = 0;
128         for (AnnotationElement elem : array) {
129             sb.append(elem.toString());
130 
131             if (i++ < array.size() - 1) {
132                 sb.append(", ");
133             }
134         }
135 
136         _toString(sb);
137 
138         sb.append("}");
139         return sb.toString();
140     }
141 
142     protected void _toString(StringBuilder sb) {
143         // sub-classes override this
144     }
145 }
146