1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later. 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 */ 15 16 package javassist.bytecode; 17 18 import java.util.HashMap; 19 import java.util.Map; 20 import java.io.IOException; 21 import java.io.DataInputStream; 22 import java.io.ByteArrayOutputStream; 23 24 import javassist.bytecode.AnnotationsAttribute.Copier; 25 import javassist.bytecode.AnnotationsAttribute.Parser; 26 import javassist.bytecode.AnnotationsAttribute.Renamer; 27 import javassist.bytecode.annotation.*; 28 29 /** 30 * A class representing <code>RuntimeVisibleAnnotations_attribute</code> and 31 * <code>RuntimeInvisibleAnnotations_attribute</code>. 32 * 33 * <p>To obtain an ParameterAnnotationAttribute object, invoke 34 * <code>getAttribute(ParameterAnnotationsAttribute.invisibleTag)</code> 35 * in <code>MethodInfo</code>. 36 * The obtained attribute is a 37 * runtime invisible annotations attribute. 38 * If the parameter is 39 * <code>ParameterAnnotationAttribute.visibleTag</code>, then the obtained 40 * attribute is a runtime visible one. 41 */ 42 public class ParameterAnnotationsAttribute extends AttributeInfo { 43 /** 44 * The name of the <code>RuntimeVisibleParameterAnnotations</code> 45 * attribute. 46 */ 47 public static final String visibleTag 48 = "RuntimeVisibleParameterAnnotations"; 49 50 /** 51 * The name of the <code>RuntimeInvisibleParameterAnnotations</code> 52 * attribute. 53 */ 54 public static final String invisibleTag 55 = "RuntimeInvisibleParameterAnnotations"; 56 /** 57 * Constructs 58 * a <code>Runtime(In)VisibleParameterAnnotations_attribute</code>. 59 * 60 * @param cp constant pool 61 * @param attrname attribute name (<code>visibleTag</code> or 62 * <code>invisibleTag</code>). 63 * @param info the contents of this attribute. It does not 64 * include <code>attribute_name_index</code> or 65 * <code>attribute_length</code>. 66 */ 67 public ParameterAnnotationsAttribute(ConstPool cp, String attrname, 68 byte[] info) { 69 super(cp, attrname, info); 70 } 71 72 /** 73 * Constructs an empty 74 * <code>Runtime(In)VisibleParameterAnnotations_attribute</code>. 75 * A new annotation can be later added to the created attribute 76 * by <code>setAnnotations()</code>. 77 * 78 * @param cp constant pool 79 * @param attrname attribute name (<code>visibleTag</code> or 80 * <code>invisibleTag</code>). 81 * @see #setAnnotations(Annotation[][]) 82 */ 83 public ParameterAnnotationsAttribute(ConstPool cp, String attrname) { 84 this(cp, attrname, new byte[] { 0 }); 85 } 86 87 /** 88 * @param n the attribute name. 89 */ 90 ParameterAnnotationsAttribute(ConstPool cp, int n, DataInputStream in) 91 throws IOException 92 { 93 super(cp, n, in); 94 } 95 96 /** 97 * Returns <code>num_parameters</code>. 98 */ 99 public int numParameters() { 100 return info[0] & 0xff; 101 } 102 103 /** 104 * Copies this attribute and returns a new copy. 105 */ 106 public AttributeInfo copy(ConstPool newCp, Map classnames) { 107 Copier copier = new Copier(info, constPool, newCp, classnames); 108 try { 109 copier.parameters(); 110 return new ParameterAnnotationsAttribute(newCp, getName(), 111 copier.close()); 112 } 113 catch (Exception e) { 114 throw new RuntimeException(e.toString()); 115 } 116 } 117 118 /** 119 * Parses the annotations and returns a data structure representing 120 * that parsed annotations. Note that changes of the node values of the 121 * returned tree are not reflected on the annotations represented by 122 * this object unless the tree is copied back to this object by 123 * <code>setAnnotations()</code>. 124 * 125 * @return Each element of the returned array represents an array of 126 * annotations that are associated with each method parameter. 127 * 128 * @see #setAnnotations(Annotation[][]) 129 */ 130 public Annotation[][] getAnnotations() { 131 try { 132 return new Parser(info, constPool).parseParameters(); 133 } 134 catch (Exception e) { 135 throw new RuntimeException(e.toString()); 136 } 137 } 138 139 /** 140 * Changes the annotations represented by this object according to 141 * the given array of <code>Annotation</code> objects. 142 * 143 * @param params the data structure representing the 144 * new annotations. Every element of this array 145 * is an array of <code>Annotation</code> and 146 * it represens annotations of each method parameter. 147 */ 148 public void setAnnotations(Annotation[][] params) { 149 ByteArrayOutputStream output = new ByteArrayOutputStream(); 150 AnnotationsWriter writer = new AnnotationsWriter(output, constPool); 151 try { 152 int n = params.length; 153 writer.numParameters(n); 154 for (int i = 0; i < n; ++i) { 155 Annotation[] anno = params[i]; 156 writer.numAnnotations(anno.length); 157 for (int j = 0; j < anno.length; ++j) 158 anno[j].write(writer); 159 } 160 161 writer.close(); 162 } 163 catch (IOException e) { 164 throw new RuntimeException(e); // should never reach here. 165 } 166 167 set(output.toByteArray()); 168 } 169 170 /** 171 * @param oldname a JVM class name. 172 * @param newname a JVM class name. 173 */ 174 void renameClass(String oldname, String newname) { 175 HashMap map = new HashMap(); 176 map.put(oldname, newname); 177 renameClass(map); 178 } 179 180 void renameClass(Map classnames) { 181 Renamer renamer = new Renamer(info, getConstPool(), classnames); 182 try { 183 renamer.parameters(); 184 } catch (Exception e) { 185 throw new RuntimeException(e); 186 } 187 } 188 189 void getRefClasses(Map classnames) { renameClass(classnames); } 190 191 /** 192 * Returns a string representation of this object. 193 */ 194 public String toString() { 195 Annotation[][] aa = getAnnotations(); 196 StringBuilder sbuf = new StringBuilder(); 197 int k = 0; 198 while (k < aa.length) { 199 Annotation[] a = aa[k++]; 200 int i = 0; 201 while (i < a.length) { 202 sbuf.append(a[i++].toString()); 203 if (i != a.length) 204 sbuf.append(" "); 205 } 206 207 if (k != aa.length) 208 sbuf.append(", "); 209 } 210 211 return sbuf.toString(); 212 213 } 214 } 215