1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.bcel.classfile;
20
21 import java.io.DataInput;
22 import java.io.DataOutputStream;
23 import java.io.IOException;
24 import java.util.Iterator;
25 import java.util.stream.Stream;
26
27 import org.apache.bcel.Const;
28 import org.apache.bcel.util.Args;
29
30 /**
31 * base class for annotations
32 *
33 * @since 6.0
34 */
35 public abstract class Annotations extends Attribute implements Iterable<AnnotationEntry> {
36
37 private AnnotationEntry[] annotationTable;
38 private final boolean isRuntimeVisible;
39
40 /**
41 * Constructs an instance.
42 *
43 * @param annotationType The subclass type of the annotation.
44 * @param nameIndex Index pointing to the name <em>Code</em>.
45 * @param length Content length in bytes.
46 * @param annotationTable The actual annotations.
47 * @param constantPool Array of constants.
48 * @param isRuntimeVisible whether this Annotation visible at runtime.
49 */
50 public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable,
51 final ConstantPool constantPool, final boolean isRuntimeVisible) {
52 super(annotationType, nameIndex, length, constantPool);
53 setAnnotationTable(annotationTable);
54 this.isRuntimeVisible = isRuntimeVisible;
55 }
56
57 /**
58 * Constructs an instance.
59 *
60 * @param annotationType The subclass type of the annotation.
61 * @param nameIndex Index pointing to the name <em>Code</em>.
62 * @param length Content length in bytes.
63 * @param input Input stream.
64 * @param constantPool Array of constants.
65 * @param isRuntimeVisible whether this Annotation visible at runtime.
66 * @throws IOException Thrown if an I/O error occurs.
67 */
68 Annotations(final byte annotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool,
69 final boolean isRuntimeVisible) throws IOException {
70 this(annotationType, nameIndex, length, (AnnotationEntry[]) null, constantPool, isRuntimeVisible);
71 final int annotationTableLength = input.readUnsignedShort();
72 annotationTable = new AnnotationEntry[annotationTableLength];
73 for (int i = 0; i < annotationTableLength; i++) {
74 annotationTable[i] = AnnotationEntry.read(input, constantPool, isRuntimeVisible);
75 }
76 }
77
78 /**
79 * Called by objects that are traversing the nodes of the tree implicitly
80 * defined by the contents of a Java class. I.e., the hierarchy of methods,
81 * fields, attributes, etc. spawns a tree of objects.
82 *
83 * @param v Visitor object.
84 */
85 @Override
86 public void accept(final Visitor v) {
87 v.visitAnnotation(this);
88 }
89
90 @Override
91 public Attribute copy(final ConstantPool constantPool) {
92 // TODO Auto-generated method stub
93 return null;
94 }
95
96 /**
97 * Gets the array of annotation entries in this annotation.
98 *
99 * @return The array of annotation entries in this annotation.
100 */
101 public AnnotationEntry[] getAnnotationEntries() {
102 return annotationTable;
103 }
104
105 /**
106 * Gets the number of annotation entries in this annotation.
107 *
108 * @return The number of annotation entries in this annotation.
109 */
110 public final int getNumAnnotations() {
111 return annotationTable.length;
112 }
113
114 /**
115 * Gets whether this annotation is runtime visible.
116 *
117 * @return true if this annotation is runtime visible.
118 */
119 public boolean isRuntimeVisible() {
120 return isRuntimeVisible;
121 }
122
123 @Override
124 public Iterator<AnnotationEntry> iterator() {
125 return Stream.of(annotationTable).iterator();
126 }
127
128 /**
129 * Sets the entries to set in this annotation.
130 *
131 * @param annotationTable The entries to set in this annotation.
132 */
133 public final void setAnnotationTable(final AnnotationEntry[] annotationTable) {
134 this.annotationTable = annotationTable != null ? annotationTable : AnnotationEntry.EMPTY_ARRAY;
135 }
136
137 /**
138 * Converts to a String representation.
139 *
140 * @return String representation.
141 */
142 @Override
143 public final String toString() {
144 final StringBuilder buf = new StringBuilder(Const.getAttributeName(getTag()));
145 buf.append(":\n");
146 for (int i = 0; i < annotationTable.length; i++) {
147 buf.append(" ").append(annotationTable[i]);
148 if (i < annotationTable.length - 1) {
149 buf.append('\n');
150 }
151 }
152 return buf.toString();
153 }
154
155 /**
156 * Writes the annotations to a DataOutputStream.
157 *
158 * @param dos The data output stream.
159 * @throws IOException Thrown if an I/O error occurs.
160 */
161 protected void writeAnnotations(final DataOutputStream dos) throws IOException {
162 dos.writeShort(Args.requireU2(annotationTable.length, "annotationTable.length"));
163 for (final AnnotationEntry element : annotationTable) {
164 element.dump(dos);
165 }
166 }
167
168 }