001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.bcel.classfile; 018 019import java.io.DataInput; 020import java.io.DataOutputStream; 021import java.io.IOException; 022import java.util.Iterator; 023import java.util.stream.Stream; 024 025import org.apache.bcel.Const; 026 027/** 028 * base class for annotations 029 * 030 * @since 6.0 031 */ 032public abstract class Annotations extends Attribute implements Iterable<AnnotationEntry> { 033 034 private AnnotationEntry[] annotationTable; 035 private final boolean isRuntimeVisible; 036 037 /** 038 * Constructs an instance. 039 * 040 * @param annotationType the subclass type of the annotation 041 * @param nameIndex Index pointing to the name <em>Code</em> 042 * @param length Content length in bytes 043 * @param annotationTable the actual annotations 044 * @param constantPool Array of constants 045 * @param isRuntimeVisible whether this Annotation visible at runtime 046 */ 047 public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable, 048 final ConstantPool constantPool, final boolean isRuntimeVisible) { 049 super(annotationType, nameIndex, length, constantPool); 050 this.annotationTable = annotationTable; 051 this.isRuntimeVisible = isRuntimeVisible; 052 } 053 054 /** 055 * Constructs an instance. 056 * 057 * @param annotationType the subclass type of the annotation 058 * @param nameIndex Index pointing to the name <em>Code</em> 059 * @param length Content length in bytes 060 * @param input Input stream 061 * @param constantPool Array of constants 062 * @param isRuntimeVisible whether this Annotation visible at runtime 063 * @throws IOException if an I/O error occurs. 064 */ 065 Annotations(final byte annotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool, 066 final boolean isRuntimeVisible) throws IOException { 067 this(annotationType, nameIndex, length, (AnnotationEntry[]) null, constantPool, isRuntimeVisible); 068 final int annotationTableLength = input.readUnsignedShort(); 069 annotationTable = new AnnotationEntry[annotationTableLength]; 070 for (int i = 0; i < annotationTableLength; i++) { 071 annotationTable[i] = AnnotationEntry.read(input, constantPool, isRuntimeVisible); 072 } 073 } 074 075 /** 076 * Called by objects that are traversing the nodes of the tree implicitly 077 * defined by the contents of a Java class. I.e., the hierarchy of methods, 078 * fields, attributes, etc. spawns a tree of objects. 079 * 080 * @param v Visitor object 081 */ 082 @Override 083 public void accept(final Visitor v) { 084 v.visitAnnotation(this); 085 } 086 087 @Override 088 public Attribute copy(final ConstantPool constantPool) { 089 // TODO Auto-generated method stub 090 return null; 091 } 092 093 /** 094 * Gets the array of annotation entries in this annotation 095 */ 096 public AnnotationEntry[] getAnnotationEntries() { 097 return annotationTable; 098 } 099 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}