View Javadoc
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 }