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
29 /**
30 * base class for annotations
31 *
32 * @since 6.0
33 */
34 public abstract class Annotations extends Attribute implements Iterable<AnnotationEntry> {
35
36 private AnnotationEntry[] annotationTable;
37 private final boolean isRuntimeVisible;
38
39 /**
40 * Constructs an instance.
41 *
42 * @param annotationType the subclass type of the annotation
43 * @param nameIndex Index pointing to the name <em>Code</em>
44 * @param length Content length in bytes
45 * @param annotationTable the actual annotations
46 * @param constantPool Array of constants
47 * @param isRuntimeVisible whether this Annotation visible at runtime
48 */
49 public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable,
50 final ConstantPool constantPool, final boolean isRuntimeVisible) {
51 super(annotationType, nameIndex, length, constantPool);
52 setAnnotationTable(annotationTable);
53 this.isRuntimeVisible = isRuntimeVisible;
54 }
55
56 /**
57 * Constructs an instance.
58 *
59 * @param annotationType the subclass type of the annotation
60 * @param nameIndex Index pointing to the name <em>Code</em>
61 * @param length Content length in bytes
62 * @param input Input stream
63 * @param constantPool Array of constants
64 * @param isRuntimeVisible whether this Annotation visible at runtime
65 * @throws IOException if an I/O error occurs.
66 */
67 Annotations(final byte annotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool,
68 final boolean isRuntimeVisible) throws IOException {
69 this(annotationType, nameIndex, length, (AnnotationEntry[]) null, constantPool, isRuntimeVisible);
70 final int annotationTableLength = input.readUnsignedShort();
71 annotationTable = new AnnotationEntry[annotationTableLength];
72 for (int i = 0; i < annotationTableLength; i++) {
73 annotationTable[i] = AnnotationEntry.read(input, constantPool, isRuntimeVisible);
74 }
75 }
76
77 /**
78 * Called by objects that are traversing the nodes of the tree implicitly
79 * defined by the contents of a Java class. I.e., the hierarchy of methods,
80 * fields, attributes, etc. spawns a tree of objects.
81 *
82 * @param v Visitor object
83 */
84 @Override
85 public void accept(final Visitor v) {
86 v.visitAnnotation(this);
87 }
88
89 @Override
90 public Attribute copy(final ConstantPool constantPool) {
91 // TODO Auto-generated method stub
92 return null;
93 }
94
95 /**
96 * Gets the array of annotation entries in this annotation
97 */
98 public AnnotationEntry[] getAnnotationEntries() {
99 return annotationTable;
100 }
101
102 /**
103 * Gets the number of annotation entries in this annotation.
104 *
105 * @return the number of annotation entries in this annotation
106 */
107 public final int getNumAnnotations() {
108 return annotationTable.length;
109 }
110
111 public boolean isRuntimeVisible() {
112 return isRuntimeVisible;
113 }
114
115 @Override
116 public Iterator<AnnotationEntry> iterator() {
117 return Stream.of(annotationTable).iterator();
118 }
119
120 /**
121 * Sets the entries to set in this annotation.
122 *
123 * @param annotationTable the entries to set in this annotation
124 */
125 public final void setAnnotationTable(final AnnotationEntry[] annotationTable) {
126 this.annotationTable = annotationTable != null ? annotationTable : AnnotationEntry.EMPTY_ARRAY;
127 }
128
129 /**
130 * Converts to a String representation.
131 *
132 * @return String representation
133 */
134 @Override
135 public final String toString() {
136 final StringBuilder buf = new StringBuilder(Const.getAttributeName(getTag()));
137 buf.append(":\n");
138 for (int i = 0; i < annotationTable.length; i++) {
139 buf.append(" ").append(annotationTable[i]);
140 if (i < annotationTable.length - 1) {
141 buf.append('\n');
142 }
143 }
144 return buf.toString();
145 }
146
147 protected void writeAnnotations(final DataOutputStream dos) throws IOException {
148 dos.writeShort(annotationTable.length);
149 for (final AnnotationEntry element : annotationTable) {
150 element.dump(dos);
151 }
152 }
153
154 }