javap/src/main/java/org/apidesign/javap/AnnotationParser.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 12:58:12 +0100
branchemul
changeset 694 0d277415ed02
parent 655 044c72732424
permissions -rw-r--r--
Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
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
}