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.ArrayList;
23  import java.util.List;
24  import java.util.stream.Stream;
25  
26  import org.apache.commons.lang3.stream.Streams;
27  
28  /**
29   * Represents one annotation in the annotation table
30   *
31   * @since 6.0
32   */
33  public class AnnotationEntry implements Node {
34  
35      public static final AnnotationEntry[] EMPTY_ARRAY = {};
36  
37      public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attributes) {
38          // Find attributes that contain annotation data
39          return Streams.of(attributes).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries()))
40                  .toArray(AnnotationEntry[]::new);
41      }
42  
43      /**
44       * Factory method to create an AnnotionEntry from a DataInput
45       *
46       * @param input
47       * @param constantPool
48       * @param isRuntimeVisible
49       * @return the entry
50       * @throws IOException if an I/O error occurs.
51       */
52      public static AnnotationEntry read(final DataInput input, final ConstantPool constantPool, final boolean isRuntimeVisible) throws IOException {
53          final AnnotationEntry annotationEntry = new AnnotationEntry(input.readUnsignedShort(), constantPool, isRuntimeVisible);
54          final int numElementValuePairs = input.readUnsignedShort();
55          for (int i = 0; i < numElementValuePairs; i++) {
56              annotationEntry.elementValuePairs
57                  .add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool));
58          }
59          return annotationEntry;
60      }
61  
62      private final int typeIndex;
63  
64      private final ConstantPool constantPool;
65  
66      private final boolean isRuntimeVisible;
67  
68      private final List<ElementValuePair> elementValuePairs;
69  
70      public AnnotationEntry(final int typeIndex, final ConstantPool constantPool, final boolean isRuntimeVisible) {
71          this.typeIndex = typeIndex;
72          this.constantPool = constantPool;
73          this.isRuntimeVisible = isRuntimeVisible;
74          this.elementValuePairs = new ArrayList<>();
75      }
76  
77      /**
78       * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
79       * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
80       *
81       * @param v Visitor object
82       */
83      @Override
84      public void accept(final Visitor v) {
85          v.visitAnnotationEntry(this);
86      }
87  
88      public void addElementNameValuePair(final ElementValuePair elementNameValuePair) {
89          elementValuePairs.add(elementNameValuePair);
90      }
91  
92      public void dump(final DataOutputStream dos) throws IOException {
93          dos.writeShort(typeIndex); // u2 index of type name in cpool
94          dos.writeShort(elementValuePairs.size()); // u2 element_value pair
95          // count
96          for (final ElementValuePair envp : elementValuePairs) {
97              envp.dump(dos);
98          }
99      }
100 
101     /**
102      * @return the annotation type name
103      */
104     public String getAnnotationType() {
105         return constantPool.getConstantUtf8(typeIndex).getBytes();
106     }
107 
108     /**
109      * @return the annotation type index
110      */
111     public int getAnnotationTypeIndex() {
112         return typeIndex;
113     }
114 
115     public ConstantPool getConstantPool() {
116         return constantPool;
117     }
118 
119     /**
120      * @return the element value pairs in this annotation entry
121      */
122     public ElementValuePair[] getElementValuePairs() {
123         // TODO return List
124         return elementValuePairs.toArray(ElementValuePair.EMPTY_ARRAY);
125     }
126 
127     /**
128      * @return the number of element value pairs in this annotation entry
129      */
130     public final int getNumElementValuePairs() {
131         return elementValuePairs.size();
132     }
133 
134     public int getTypeIndex() {
135         return typeIndex;
136     }
137 
138     public boolean isRuntimeVisible() {
139         return isRuntimeVisible;
140     }
141 
142     public String toShortString() {
143         final StringBuilder result = new StringBuilder();
144         result.append("@");
145         result.append(getAnnotationType());
146         final ElementValuePair[] evPairs = getElementValuePairs();
147         if (evPairs.length > 0) {
148             result.append("(");
149             for (final ElementValuePair element : evPairs) {
150                 result.append(element.toShortString());
151                 result.append(", ");
152             }
153             // remove last ", "
154             result.setLength(result.length() - 2);
155             result.append(")");
156         }
157         return result.toString();
158     }
159 
160     @Override
161     public String toString() {
162         return toShortString();
163     }
164 }