Home | History | Annotate | Download | only in bytecode
      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