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