javap/src/main/java/org/apidesign/javap/AnnotationParser.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 05 Feb 2013 08:48:23 +0100
branchemul
changeset 667 5866e89ef568
parent 655 044c72732424
permissions -rw-r--r--
Test can specify multiple HTTP resources
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@659
    45
    protected void visitAnnotationStart(String type, boolean top) throws IOException {
jaroslav@235
    46
    }
jaroslav@235
    47
jaroslav@659
    48
    protected void visitAnnotationEnd(String type, boolean top) 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@655
    63
    protected void visitEnumAttr(
jaroslav@655
    64
        String annoType, String attr, String attrType, String value
jaroslav@655
    65
    ) throws IOException {
jaroslav@655
    66
        visitAttr(annoType, attr, attrType, value);
jaroslav@655
    67
    }
jaroslav@655
    68
    
jaroslav@152
    69
    /** Initialize the parsing with constant pool from <code>cd</code>.
jaroslav@152
    70
     * 
jaroslav@152
    71
     * @param attr the attribute defining annotations
jaroslav@152
    72
     * @param cd constant pool
jaroslav@152
    73
     * @throws IOException in case I/O fails
jaroslav@152
    74
     */
jaroslav@152
    75
    public final void parse(byte[] attr, ClassData cd) throws IOException {
jaroslav@152
    76
        ByteArrayInputStream is = new ByteArrayInputStream(attr);
jaroslav@152
    77
        DataInputStream dis = new DataInputStream(is);
jaroslav@152
    78
        try {
jaroslav@152
    79
            read(dis, cd);
jaroslav@152
    80
        } finally {
jaroslav@152
    81
            is.close();
jaroslav@152
    82
        }
jaroslav@152
    83
    }
jaroslav@152
    84
    
jaroslav@152
    85
    private void read(DataInputStream dis, ClassData cd) throws IOException {
jaroslav@152
    86
    	int cnt = dis.readUnsignedShort();
jaroslav@152
    87
        for (int i = 0; i < cnt; i++) {
jaroslav@659
    88
            readAnno(dis, cd, true);
jaroslav@152
    89
        }
jaroslav@152
    90
    }
jaroslav@152
    91
jaroslav@659
    92
    private void readAnno(DataInputStream dis, ClassData cd, boolean top) throws IOException {
jaroslav@152
    93
        int type = dis.readUnsignedShort();
jaroslav@152
    94
        String typeName = cd.StringValue(type);
jaroslav@659
    95
        visitAnnotationStart(typeName, top);
jaroslav@152
    96
    	int cnt = dis.readUnsignedShort();
jaroslav@152
    97
    	for (int i = 0; i < cnt; i++) {
jaroslav@153
    98
            String attrName = cd.StringValue(dis.readUnsignedShort());
jaroslav@153
    99
            readValue(dis, cd, typeName, attrName);
jaroslav@152
   100
        }
jaroslav@659
   101
        visitAnnotationEnd(typeName, top);
jaroslav@240
   102
        if (cnt == 0) {
jaroslav@249
   103
            visitAttr(typeName, null, null, null);
jaroslav@240
   104
        }
jaroslav@152
   105
    }
jaroslav@152
   106
jaroslav@652
   107
    private void readValue(
jaroslav@652
   108
        DataInputStream dis, ClassData cd, String typeName, String attrName
jaroslav@652
   109
    ) throws IOException {
jaroslav@152
   110
        char type = (char)dis.readByte();
jaroslav@652
   111
        visitValueStart(attrName, type);
jaroslav@152
   112
        if (type == '@') {
jaroslav@659
   113
            readAnno(dis, cd, false);
jaroslav@152
   114
        } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
jaroslav@152
   115
            int primitive = dis.readUnsignedShort();
jaroslav@237
   116
            String val = cd.stringValue(primitive, textual);
jaroslav@236
   117
            String attrType;
jaroslav@236
   118
            if (type == 's') {
jaroslav@252
   119
                attrType = "Ljava_lang_String_2";
jaroslav@237
   120
                if (textual) {
jaroslav@237
   121
                    val = '"' + val + '"';
jaroslav@237
   122
                }
jaroslav@236
   123
            } else {
jaroslav@236
   124
                attrType = "" + type;
jaroslav@236
   125
            }
jaroslav@237
   126
            visitAttr(typeName, attrName, attrType, val);
jaroslav@152
   127
        } else if (type == 'c') {
jaroslav@152
   128
            int cls = dis.readUnsignedShort();
jaroslav@152
   129
        } else if (type == '[') {
jaroslav@152
   130
            int cnt = dis.readUnsignedShort();
jaroslav@152
   131
            for (int i = 0; i < cnt; i++) {
jaroslav@652
   132
                readValue(dis, cd, typeName, iterateArray ? attrName : null);
jaroslav@152
   133
            }
jaroslav@152
   134
        } else if (type == 'e') {
jaroslav@152
   135
            int enumT = dis.readUnsignedShort();
jaroslav@652
   136
            String attrType = cd.stringValue(enumT, textual);
jaroslav@152
   137
            int enumN = dis.readUnsignedShort();
jaroslav@652
   138
            String val = cd.stringValue(enumN, textual);
jaroslav@655
   139
            visitEnumAttr(typeName, attrName, attrType, val);
jaroslav@152
   140
        } else {
jaroslav@152
   141
            throw new IOException("Unknown type " + type);
jaroslav@152
   142
        }
jaroslav@652
   143
        visitValueEnd(attrName, type);
jaroslav@152
   144
    }
jaroslav@152
   145
}