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