Home | History | Annotate | Download | only in tree
      1 /***
      2  * ASM: a very small and fast Java bytecode manipulation framework
      3  * Copyright (c) 2000-2007 INRIA, France Telecom
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. Neither the name of the copyright holders nor the names of its
     15  *    contributors may be used to endorse or promote products derived from
     16  *    this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     28  * THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 package org.mockito.asm.tree;
     31 
     32 import java.util.ArrayList;
     33 import java.util.List;
     34 
     35 import org.mockito.asm.AnnotationVisitor;
     36 
     37 /**
     38  * A node that represents an annotationn.
     39  *
     40  * @author Eric Bruneton
     41  */
     42 public class AnnotationNode implements AnnotationVisitor {
     43 
     44     /**
     45      * The class descriptor of the annotation class.
     46      */
     47     public String desc;
     48 
     49     /**
     50      * The name value pairs of this annotation. Each name value pair is stored
     51      * as two consecutive elements in the list. The name is a {@link String},
     52      * and the value may be a {@link Byte}, {@link Boolean}, {@link Character},
     53      * {@link Short}, {@link Integer}, {@link Long}, {@link Float},
     54      * {@link Double}, {@link String} or {@link org.mockito.asm.Type}, or an
     55      * two elements String array (for enumeration values), a
     56      * {@link AnnotationNode}, or a {@link List} of values of one of the
     57      * preceding types. The list may be <tt>null</tt> if there is no name
     58      * value pair.
     59      */
     60     public List values;
     61 
     62     /**
     63      * Constructs a new {@link AnnotationNode}.
     64      *
     65      * @param desc the class descriptor of the annotation class.
     66      */
     67     public AnnotationNode(final String desc) {
     68         this.desc = desc;
     69     }
     70 
     71     /**
     72      * Constructs a new {@link AnnotationNode} to visit an array value.
     73      *
     74      * @param values where the visited values must be stored.
     75      */
     76     AnnotationNode(final List values) {
     77         this.values = values;
     78     }
     79 
     80     // ------------------------------------------------------------------------
     81     // Implementation of the AnnotationVisitor interface
     82     // ------------------------------------------------------------------------
     83 
     84     public void visit(final String name, final Object value) {
     85         if (values == null) {
     86             values = new ArrayList(this.desc != null ? 2 : 1);
     87         }
     88         if (this.desc != null) {
     89             values.add(name);
     90         }
     91         values.add(value);
     92     }
     93 
     94     public void visitEnum(
     95         final String name,
     96         final String desc,
     97         final String value)
     98     {
     99         if (values == null) {
    100             values = new ArrayList(this.desc != null ? 2 : 1);
    101         }
    102         if (this.desc != null) {
    103             values.add(name);
    104         }
    105         values.add(new String[] { desc, value });
    106     }
    107 
    108     public AnnotationVisitor visitAnnotation(
    109         final String name,
    110         final String desc)
    111     {
    112         if (values == null) {
    113             values = new ArrayList(this.desc != null ? 2 : 1);
    114         }
    115         if (this.desc != null) {
    116             values.add(name);
    117         }
    118         AnnotationNode annotation = new AnnotationNode(desc);
    119         values.add(annotation);
    120         return annotation;
    121     }
    122 
    123     public AnnotationVisitor visitArray(final String name) {
    124         if (values == null) {
    125             values = new ArrayList(this.desc != null ? 2 : 1);
    126         }
    127         if (this.desc != null) {
    128             values.add(name);
    129         }
    130         List array = new ArrayList();
    131         values.add(array);
    132         return new AnnotationNode(array);
    133     }
    134 
    135     public void visitEnd() {
    136     }
    137 
    138     // ------------------------------------------------------------------------
    139     // Accept methods
    140     // ------------------------------------------------------------------------
    141 
    142     /**
    143      * Makes the given visitor visit this annotation.
    144      *
    145      * @param av an annotation visitor. Maybe <tt>null</tt>.
    146      */
    147     public void accept(final AnnotationVisitor av) {
    148         if (av != null) {
    149             if (values != null) {
    150                 for (int i = 0; i < values.size(); i += 2) {
    151                     String name = (String) values.get(i);
    152                     Object value = values.get(i + 1);
    153                     accept(av, name, value);
    154                 }
    155             }
    156             av.visitEnd();
    157         }
    158     }
    159 
    160     /**
    161      * Makes the given visitor visit a given annotation value.
    162      *
    163      * @param av an annotation visitor. Maybe <tt>null</tt>.
    164      * @param name the value name.
    165      * @param value the actual value.
    166      */
    167     static void accept(
    168         final AnnotationVisitor av,
    169         final String name,
    170         final Object value)
    171     {
    172         if (av != null) {
    173             if (value instanceof String[]) {
    174                 String[] typeconst = (String[]) value;
    175                 av.visitEnum(name, typeconst[0], typeconst[1]);
    176             } else if (value instanceof AnnotationNode) {
    177                 AnnotationNode an = (AnnotationNode) value;
    178                 an.accept(av.visitAnnotation(name, an.desc));
    179             } else if (value instanceof List) {
    180                 AnnotationVisitor v = av.visitArray(name);
    181                 List array = (List) value;
    182                 for (int j = 0; j < array.size(); ++j) {
    183                     accept(v, null, array.get(j));
    184                 }
    185                 v.visitEnd();
    186             } else {
    187                 av.visit(name, value);
    188             }
    189         }
    190     }
    191 }
    192