AnnotationEntry.java

  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. import java.io.DataInput;
  19. import java.io.DataOutputStream;
  20. import java.io.IOException;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. import java.util.stream.Stream;

  24. import org.apache.commons.lang3.stream.Streams;

  25. /**
  26.  * Represents one annotation in the annotation table
  27.  *
  28.  * @since 6.0
  29.  */
  30. public class AnnotationEntry implements Node {

  31.     public static final AnnotationEntry[] EMPTY_ARRAY = {};

  32.     public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attributes) {
  33.         // Find attributes that contain annotation data
  34.         return Streams.of(attributes).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries()))
  35.                 .toArray(AnnotationEntry[]::new);
  36.     }

  37.     /**
  38.      * Factory method to create an AnnotionEntry from a DataInput
  39.      *
  40.      * @param input
  41.      * @param constantPool
  42.      * @param isRuntimeVisible
  43.      * @return the entry
  44.      * @throws IOException if an I/O error occurs.
  45.      */
  46.     public static AnnotationEntry read(final DataInput input, final ConstantPool constantPool, final boolean isRuntimeVisible) throws IOException {
  47.         final AnnotationEntry annotationEntry = new AnnotationEntry(input.readUnsignedShort(), constantPool, isRuntimeVisible);
  48.         final int numElementValuePairs = input.readUnsignedShort();
  49.         for (int i = 0; i < numElementValuePairs; i++) {
  50.             annotationEntry.elementValuePairs
  51.                 .add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool));
  52.         }
  53.         return annotationEntry;
  54.     }

  55.     private final int typeIndex;

  56.     private final ConstantPool constantPool;

  57.     private final boolean isRuntimeVisible;

  58.     private final List<ElementValuePair> elementValuePairs;

  59.     public AnnotationEntry(final int typeIndex, final ConstantPool constantPool, final boolean isRuntimeVisible) {
  60.         this.typeIndex = typeIndex;
  61.         this.constantPool = constantPool;
  62.         this.isRuntimeVisible = isRuntimeVisible;
  63.         this.elementValuePairs = new ArrayList<>();
  64.     }

  65.     /**
  66.      * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
  67.      * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
  68.      *
  69.      * @param v Visitor object
  70.      */
  71.     @Override
  72.     public void accept(final Visitor v) {
  73.         v.visitAnnotationEntry(this);
  74.     }

  75.     public void addElementNameValuePair(final ElementValuePair elementNameValuePair) {
  76.         elementValuePairs.add(elementNameValuePair);
  77.     }

  78.     public void dump(final DataOutputStream dos) throws IOException {
  79.         dos.writeShort(typeIndex); // u2 index of type name in cpool
  80.         dos.writeShort(elementValuePairs.size()); // u2 element_value pair
  81.         // count
  82.         for (final ElementValuePair envp : elementValuePairs) {
  83.             envp.dump(dos);
  84.         }
  85.     }

  86.     /**
  87.      * @return the annotation type name
  88.      */
  89.     public String getAnnotationType() {
  90.         return constantPool.getConstantUtf8(typeIndex).getBytes();
  91.     }

  92.     /**
  93.      * @return the annotation type index
  94.      */
  95.     public int getAnnotationTypeIndex() {
  96.         return typeIndex;
  97.     }

  98.     public ConstantPool getConstantPool() {
  99.         return constantPool;
  100.     }

  101.     /**
  102.      * @return the element value pairs in this annotation entry
  103.      */
  104.     public ElementValuePair[] getElementValuePairs() {
  105.         // TODO return List
  106.         return elementValuePairs.toArray(ElementValuePair.EMPTY_ARRAY);
  107.     }

  108.     /**
  109.      * @return the number of element value pairs in this annotation entry
  110.      */
  111.     public final int getNumElementValuePairs() {
  112.         return elementValuePairs.size();
  113.     }

  114.     public int getTypeIndex() {
  115.         return typeIndex;
  116.     }

  117.     public boolean isRuntimeVisible() {
  118.         return isRuntimeVisible;
  119.     }

  120.     public String toShortString() {
  121.         final StringBuilder result = new StringBuilder();
  122.         result.append("@");
  123.         result.append(getAnnotationType());
  124.         final ElementValuePair[] evPairs = getElementValuePairs();
  125.         if (evPairs.length > 0) {
  126.             result.append("(");
  127.             for (final ElementValuePair element : evPairs) {
  128.                 result.append(element.toShortString());
  129.                 result.append(", ");
  130.             }
  131.             // remove last ", "
  132.             result.setLength(result.length() - 2);
  133.             result.append(")");
  134.         }
  135.         return result.toString();
  136.     }

  137.     @Override
  138.     public String toString() {
  139.         return toShortString();
  140.     }
  141. }