javap/src/main/java/org/apidesign/javap/AnnotationParser.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 03 Feb 2013 18:58:09 +0100
branchreflection
changeset 652 f095ea52f417
parent 252 55d2676f82c9
child 653 bcdfc29fd004
permissions -rw-r--r--
Supporting annotations with arrays
jaroslav@152
     1
/*
jaroslav@152
     2
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
jaroslav@152
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jaroslav@152
     4
 *
jaroslav@152
     5
 * This code is free software; you can redistribute it and/or modify it
jaroslav@152
     6
 * under the terms of the GNU General Public License version 2 only, as
jaroslav@152
     7
 * published by the Free Software Foundation.  Oracle designates this
jaroslav@152
     8
 * particular file as subject to the "Classpath" exception as provided
jaroslav@152
     9
 * by Oracle in the LICENSE file that accompanied this code.
jaroslav@152
    10
 *
jaroslav@152
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
jaroslav@152
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jaroslav@152
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jaroslav@152
    14
 * version 2 for more details (a copy is included in the LICENSE file that
jaroslav@152
    15
 * accompanied this code).
jaroslav@152
    16
 *
jaroslav@152
    17
 * You should have received a copy of the GNU General Public License version
jaroslav@152
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
jaroslav@152
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jaroslav@152
    20
 *
jaroslav@152
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jaroslav@152
    22
 * or visit www.oracle.com if you need additional information or have any
jaroslav@152
    23
 * questions.
jaroslav@152
    24
 */
jtulach@167
    25
package org.apidesign.javap;
jaroslav@152
    26
jaroslav@152
    27
import java.io.ByteArrayInputStream;
jaroslav@152
    28
import java.io.DataInputStream;
jaroslav@152
    29
import java.io.IOException;
jaroslav@152
    30
jaroslav@152
    31
/** An abstract parser for annotation definitions. Analyses the bytes and
jaroslav@152
    32
 * performs some callbacks to the overriden parser methods.
jaroslav@152
    33
 *
jaroslav@152
    34
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@152
    35
 */
jaroslav@152
    36
public class AnnotationParser {
jaroslav@237
    37
    private final boolean textual;
jaroslav@652
    38
    private final boolean iterateArray;
jaroslav@237
    39
    
jaroslav@652
    40
    protected AnnotationParser(boolean textual, boolean iterateArray) {
jaroslav@237
    41
        this.textual = textual;
jaroslav@652
    42
        this.iterateArray = iterateArray;
jaroslav@152
    43
    }
jaroslav@152
    44
jaroslav@235
    45
    protected void visitAnnotationStart(String type) throws IOException {
jaroslav@235
    46
    }
jaroslav@235
    47
jaroslav@235
    48
    protected void visitAnnotationEnd(String type) throws IOException {
jaroslav@235
    49
    }
jaroslav@652
    50
jaroslav@652
    51
    protected void visitValueStart(String attrName, char type) throws IOException {
jaroslav@652
    52
    }
jaroslav@652
    53
jaroslav@652
    54
    protected void visitValueEnd(String attrName, char type) throws IOException {
jaroslav@652
    55
    }
jaroslav@652
    56
jaroslav@235
    57
    
jaroslav@235
    58
    protected void visitAttr(
jaroslav@236
    59
        String annoType, String attr, String attrType, String value
jaroslav@235
    60
    ) throws IOException {
jaroslav@152
    61
    }
jaroslav@152
    62
    
jaroslav@152
    63
    /** Initialize the parsing with constant pool from <code>cd</code>.
jaroslav@152
    64
     * 
jaroslav@152
    65
     * @param attr the attribute defining annotations
jaroslav@152
    66
     * @param cd constant pool
jaroslav@152
    67
     * @throws IOException in case I/O fails
jaroslav@152
    68
     */
jaroslav@152
    69
    public final void parse(byte[] attr, ClassData cd) throws IOException {
jaroslav@152
    70
        ByteArrayInputStream is = new ByteArrayInputStream(attr);
jaroslav@152
    71
        DataInputStream dis = new DataInputStream(is);
jaroslav@152
    72
        try {
jaroslav@152
    73
            read(dis, cd);
jaroslav@152
    74
        } finally {
jaroslav@152
    75
            is.close();
jaroslav@152
    76
        }
jaroslav@152
    77
    }
jaroslav@152
    78
    
jaroslav@152
    79
    private void read(DataInputStream dis, ClassData cd) throws IOException {
jaroslav@152
    80
    	int cnt = dis.readUnsignedShort();
jaroslav@152
    81
        for (int i = 0; i < cnt; i++) {
jaroslav@152
    82
            readAnno(dis, cd);
jaroslav@152
    83
        }
jaroslav@152
    84
    }
jaroslav@152
    85
jaroslav@152
    86
    private void readAnno(DataInputStream dis, ClassData cd) throws IOException {
jaroslav@152
    87
        int type = dis.readUnsignedShort();
jaroslav@152
    88
        String typeName = cd.StringValue(type);
jaroslav@235
    89
        visitAnnotationStart(typeName);
jaroslav@152
    90
    	int cnt = dis.readUnsignedShort();
jaroslav@152
    91
    	for (int i = 0; i < cnt; i++) {
jaroslav@153
    92
            String attrName = cd.StringValue(dis.readUnsignedShort());
jaroslav@153
    93
            readValue(dis, cd, typeName, attrName);
jaroslav@152
    94
        }
jaroslav@235
    95
        visitAnnotationEnd(typeName);
jaroslav@240
    96
        if (cnt == 0) {
jaroslav@249
    97
            visitAttr(typeName, null, null, null);
jaroslav@240
    98
        }
jaroslav@152
    99
    }
jaroslav@152
   100
jaroslav@652
   101
    private void readValue(
jaroslav@652
   102
        DataInputStream dis, ClassData cd, String typeName, String attrName
jaroslav@652
   103
    ) throws IOException {
jaroslav@152
   104
        char type = (char)dis.readByte();
jaroslav@652
   105
        visitValueStart(attrName, type);
jaroslav@152
   106
        if (type == '@') {
jaroslav@152
   107
            readAnno(dis, cd);
jaroslav@152
   108
        } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
jaroslav@152
   109
            int primitive = dis.readUnsignedShort();
jaroslav@237
   110
            String val = cd.stringValue(primitive, textual);
jaroslav@236
   111
            String attrType;
jaroslav@236
   112
            if (type == 's') {
jaroslav@252
   113
                attrType = "Ljava_lang_String_2";
jaroslav@237
   114
                if (textual) {
jaroslav@237
   115
                    val = '"' + val + '"';
jaroslav@237
   116
                }
jaroslav@236
   117
            } else {
jaroslav@236
   118
                attrType = "" + type;
jaroslav@236
   119
            }
jaroslav@237
   120
            visitAttr(typeName, attrName, attrType, val);
jaroslav@152
   121
        } else if (type == 'c') {
jaroslav@152
   122
            int cls = dis.readUnsignedShort();
jaroslav@152
   123
        } else if (type == '[') {
jaroslav@152
   124
            int cnt = dis.readUnsignedShort();
jaroslav@152
   125
            for (int i = 0; i < cnt; i++) {
jaroslav@652
   126
                readValue(dis, cd, typeName, iterateArray ? attrName : null);
jaroslav@152
   127
            }
jaroslav@152
   128
        } else if (type == 'e') {
jaroslav@152
   129
            int enumT = dis.readUnsignedShort();
jaroslav@652
   130
            String attrType = cd.stringValue(enumT, textual);
jaroslav@152
   131
            int enumN = dis.readUnsignedShort();
jaroslav@652
   132
            String val = cd.stringValue(enumN, textual);
jaroslav@652
   133
            if (textual) {
jaroslav@652
   134
                val = '"' + val + '"';
jaroslav@652
   135
            }
jaroslav@652
   136
            visitAttr(typeName, attrName, attrType, val);
jaroslav@152
   137
        } else {
jaroslav@152
   138
            throw new IOException("Unknown type " + type);
jaroslav@152
   139
        }
jaroslav@652
   140
        visitValueEnd(attrName, type);
jaroslav@152
   141
    }
jaroslav@152
   142
}