package edu.umd.cs.findbugs.visitclass;
import java.util.*;
import java.io.PrintStream;
import org.apache.bcel.classfile.*;
import java.util.zip.*;
import java.io.*;

public class AnnotationVisitor extends PreorderVisitor {

    static final boolean DEBUG = false;

    public void visitAnnotation(String annotationClass, Map<String, Object> map, boolean runtimeVisible)  {
	System.out.println("Annotation: " + annotationClass);
	for(Map.Entry<String,Object>  e : map.entrySet()) {
		System.out.println("    " + e.getKey());
		System.out.println(" -> " + e.getValue());
		}
	}
    public void visit(Attribute obj)  {
        try {
            if (obj instanceof Unknown) {
                String name = ((Unknown)obj).getName();
                if (DEBUG) 
		System.out.println("In " + getDottedClassName() + " found " + 
                    name);
                if (!(name.equals("RuntimeVisibleAnnotations") || name.equals("RuntimeInvisibleAnnotations"))) return;
                byte [] b = ((Unknown)obj).getBytes();
                DataInputStream bytes = new DataInputStream(new ByteArrayInputStream(b));
                int numAnnotations = bytes.readUnsignedShort();
                if (DEBUG)
		System.out.println("# of annotations: " + numAnnotations);
                for(int i = 0; i < numAnnotations; i++) {
                    int annotationNameIndex = bytes.readUnsignedShort();
            		String annotationName = 
	((ConstantUtf8)getConstantPool().getConstant(annotationNameIndex)).getBytes();
			annotationName = annotationName.substring(1,annotationName.length()-1);
                if (DEBUG)
                    System.out.println("Annotation name: " + annotationName);
                    int numPairs = bytes.readUnsignedShort();
		    Map<String,Object> values = new HashMap<String,Object>();
                    for(int j = 0; j < numPairs; j++) {
                        int memberNameIndex = bytes.readUnsignedShort();
            		String memberName = 
	((ConstantUtf8)getConstantPool().getConstant(memberNameIndex)).getBytes();
                if (DEBUG)
                        System.out.println("memberName: " + memberName);
                        Object value = readAnnotationValue(bytes);
                if (DEBUG)
			System.out.println(memberName + ":" + value);
			values.put(memberName,value);
                    }
		    visitAnnotation(annotationName, values,
				name.equals("RuntimeVisibleAnnotations"));
                }


                if (DEBUG) {
                for(int i = 0; i < b.length; i++)
                    System.out.print(Integer.toString((b[i] & 0xff), 16) + " ");
                System.out.println();
		}
            }
		
        } 
        catch (Exception e) {
            // ignore
        }
    }
    private Object readAnnotationValue(DataInputStream bytes) throws IOException {
        char tag = (char) bytes.readUnsignedByte();
                if (DEBUG) 
        System.out.println("tag: " + tag);
        switch(tag) {
        case '[':
            int sz = bytes.readUnsignedShort();
                if (DEBUG) 
            System.out.println("Array of " + sz + " entries");
            Object [] result = new Object[sz];
            for(int i = 0; i < sz; i++)
                result[i] = readAnnotationValue(bytes);
            return result;
        case 'B': 
        case 'C': 
        case 'D': 
        case 'F': 
        case 'I': 
        case 'J': 
        case 'S': 
        case 'Z': 
        case 's': 
            int cp_index = bytes.readUnsignedShort();
            Constant c  =  getConstantPool().getConstant(cp_index);
	    switch(tag) {
        case 'B': 
		return new Byte(
            		(byte) ((ConstantInteger)c).getBytes());
        case 'C': 
		return new Character(
            		(char) ((ConstantInteger)c).getBytes());
        case 'D': 
		return new Double(
            		((ConstantDouble)c).getBytes());
        case 'F': 
		return new Float(
            		((ConstantFloat)c).getBytes());
        case 'I': 
		return new Integer(
            		((ConstantInteger)c).getBytes());
        case 'J': 
		return new Long(
            		((ConstantLong)c).getBytes());
        case 'S': 
		return new Character(
            		(char) ((ConstantInteger)c).getBytes());
        case 'Z': 
		return Boolean.valueOf(
            		((ConstantInteger)c).getBytes() != 0);
        case 's': 
            return ((ConstantUtf8)c).getBytes();
	default: throw new IllegalStateException("Impossible");
	}
        default: 
            throw new IllegalArgumentException();
        }
    }
}

@@ -1,42 +1,980 @@
-package edu.umd.cs.findbugs.visitclass
+/*%0A * FindBugs - Find bugs in Java programs%0A * Copyright (C) 2003-2005 University of Maryland%0A * %0A * This library is free software; you can redistribute it and/or%0A * modify it under the terms of the GNU Lesser General Public%0A * License as published by the Free Software Foundation; either%0A * version 2.1 of the License, or (at your option) any later version.%0A * %0A * This library is distributed in the hope that it will be useful,%0A * but WITHOUT ANY WARRANTY; without even the implied warranty of%0A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU%0A * Lesser General Public License for more details.%0A * %0A * You should have received a copy of the GNU Lesser General Public%0A * License along with this library; if not, write to the Free Software%0A * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA%0A */%0Apackage edu.umd.cs.findbugs.visitclass;%0A%0Aimport java.io.ByteArrayInputStream;%0Aimport java.io.DataInputStream;%0Aimport java.io.IOException
 ;%0Aim
@@ -988,17 +988,23 @@
 va.util.
-*
+HashMap
 ;%0Aimport
@@ -1013,100 +1013,387 @@
 ava.
-io.PrintStream;%0Aimport org.apache.bcel.classfile.*;%0Aimport java.util.zip.*;%0Aimport java.io.*
+util.Map;%0A%0Aimport org.apache.bcel.classfile.Attribute;%0Aimport org.apache.bcel.classfile.Constant;%0Aimport org.apache.bcel.classfile.ConstantDouble;%0Aimport org.apache.bcel.classfile.ConstantFloat;%0Aimport org.apache.bcel.classfile.ConstantInteger;%0Aimport org.apache.bcel.classfile.ConstantLong;%0Aimport org.apache.bcel.classfile.ConstantUtf8;%0Aimport org.apache.bcel.classfile.Unknown
 ;%0A%0Ap

add copyright comment