169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 2004 Bill Burke. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode.annotation;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ConstPool;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.Descriptor;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtMethod;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.NotFoundException;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException;
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.LinkedHashMap;
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Set;
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Iterator;
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The <code>annotation</code> structure.
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>An instance of this class is returned by
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>getAnnotations()</code> in <code>AnnotationsAttribute</code>
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or in <code>ParameterAnnotationsAttribute</code>.
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.bytecode.AnnotationsAttribute#getAnnotations()
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.bytecode.ParameterAnnotationsAttribute#getAnnotations()
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see MemberValue
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see MemberValueVisitor
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see AnnotationsWriter
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author Shigeru Chiba
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Annotation {
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class Pair {
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int name;
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        MemberValue value;
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    ConstPool pool;
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int typeIndex;
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    LinkedHashMap members;    // this sould be LinkedHashMap
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        // but it is not supported by JDK 1.3.
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs an annotation including no members.  A member can be
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * later added to the created annotation by <code>addMemberValue()</code>.
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param type  the index into the constant pool table.
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *              the entry at that index must be the
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *              <code>CONSTANT_Utf8_Info</code> structure
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *              repreenting the name of the annotation interface type.
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp    the constant pool table.
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #addMemberValue(String, MemberValue)
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Annotation(int type, ConstPool cp) {
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        pool = cp;
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        typeIndex = type;
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        members = null;
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs an annotation including no members.  A member can be
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * later added to the created annotation by <code>addMemberValue()</code>.
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param typeName  the name of the annotation interface type.
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp        the constant pool table.
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #addMemberValue(String, MemberValue)
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Annotation(String typeName, ConstPool cp) {
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this(cp.addUtf8Info(Descriptor.of(typeName)), cp);
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs an annotation that can be accessed through the interface
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * represented by <code>clazz</code>.  The values of the members are
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * not specified.
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp        the constant pool table.
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param clazz     the interface.
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws NotFoundException when the clazz is not found
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Annotation(ConstPool cp, CtClass clazz)
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws NotFoundException
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        // todo Enums are not supported right now.
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this(cp.addUtf8Info(Descriptor.of(clazz.getName())), cp);
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (!clazz.isInterface())
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new RuntimeException(
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                "Only interfaces are allowed for Annotation creation.");
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtMethod methods[] = clazz.getDeclaredMethods();
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (methods.length > 0) {
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            members = new LinkedHashMap();
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < methods.length; i++) {
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass returnType = methods[i].getReturnType();
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            addMemberValue(methods[i].getName(),
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                           createMemberValue(cp, returnType));
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes an instance of <code>MemberValue</code>.
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp            the constant pool table.
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param type          the type of the member.
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return the member value
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws NotFoundException when the type is not found
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static MemberValue createMemberValue(ConstPool cp, CtClass type)
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws NotFoundException
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (type == CtClass.booleanType)
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new BooleanMemberValue(cp);
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type == CtClass.byteType)
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new ByteMemberValue(cp);
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type == CtClass.charType)
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new CharMemberValue(cp);
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type == CtClass.shortType)
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new ShortMemberValue(cp);
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type == CtClass.intType)
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new IntegerMemberValue(cp);
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type == CtClass.longType)
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new LongMemberValue(cp);
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type == CtClass.floatType)
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new FloatMemberValue(cp);
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type == CtClass.doubleType)
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new DoubleMemberValue(cp);
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type.getName().equals("java.lang.Class"))
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new ClassMemberValue(cp);
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type.getName().equals("java.lang.String"))
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new StringMemberValue(cp);
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type.isArray()) {
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass arrayType = type.getComponentType();
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MemberValue member = createMemberValue(cp, arrayType);
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new ArrayMemberValue(member, cp);
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type.isInterface()) {
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Annotation info = new Annotation(cp, type);
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new AnnotationMemberValue(info, cp);
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // treat as enum.  I know this is not typed,
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // but JBoss has an Annotation Compiler for JDK 1.4
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // and I want it to work with that. - Bill Burke
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            EnumMemberValue emv = new EnumMemberValue(cp);
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            emv.setType(type.getName());
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return emv;
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adds a new member.
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param nameIndex     the index into the constant pool table.
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      The entry at that index must be
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      a <code>CONSTANT_Utf8_info</code> structure.
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                      structure representing the member name.
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param value         the member value.
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addMemberValue(int nameIndex, MemberValue value) {
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Pair p = new Pair();
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        p.name = nameIndex;
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        p.value = value;
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        addMemberValue(p);
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Adds a new member.
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name      the member name.
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param value     the member value.
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addMemberValue(String name, MemberValue value) {
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Pair p = new Pair();
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        p.name = pool.addUtf8Info(name);
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        p.value = value;
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (members == null)
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            members = new LinkedHashMap();
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        members.put(name, p);
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void addMemberValue(Pair pair) {
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String name = pool.getUtf8Info(pair.name);
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (members == null)
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            members = new LinkedHashMap();
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        members.put(name, pair);
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns a string representation of the annotation.
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String toString() {
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        StringBuffer buf = new StringBuffer("@");
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf.append(getTypeName());
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (members != null) {
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            buf.append("(");
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Iterator mit = members.keySet().iterator();
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            while (mit.hasNext()) {
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                String name = (String)mit.next();
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                buf.append(name).append("=").append(getMemberValue(name));
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (mit.hasNext())
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    buf.append(", ");
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            buf.append(")");
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return buf.toString();
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains the name of the annotation type.
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return the type name
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getTypeName() {
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return Descriptor.toClassName(pool.getUtf8Info(typeIndex));
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains all the member names.
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return null if no members are defined.
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Set getMemberNames() {
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (members == null)
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return null;
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return members.keySet();
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains the member value with the given name.
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>If this annotation does not have a value for the
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * specified member,
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this method returns null.  It does not return a
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>MemberValue</code> with the default value.
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The default value can be obtained from the annotation type.
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name the member name
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return null if the member cannot be found or if the value is
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the default value.
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see javassist.bytecode.AnnotationDefaultAttribute
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public MemberValue getMemberValue(String name) {
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (members == null)
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return null;
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Pair p = (Pair)members.get(name);
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (p == null)
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return null;
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return p.value;
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs an annotation-type object representing this annotation.
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * For example, if this annotation represents <code>@Author</code>,
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this method returns an <code>Author</code> object.
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cl        class loader for loading an annotation type.
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp        class pool for obtaining class files.
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return the annotation
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws ClassNotFoundException   if the class cannot found.
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws NoSuchClassError         if the class linkage fails.
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Object toAnnotationType(ClassLoader cl, ClassPool cp)
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws ClassNotFoundException, NoSuchClassError
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return AnnotationImpl.make(cl,
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        MemberValue.loadClass(cl, getTypeName()),
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        cp, this);
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Writes this annotation.
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param writer            the output.
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws IOException for an error during the write
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void write(AnnotationsWriter writer) throws IOException {
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String typeName = pool.getUtf8Info(typeIndex);
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (members == null) {
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.annotation(typeName, 0);
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        writer.annotation(typeName, members.size());
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Iterator it = members.values().iterator();
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (it.hasNext()) {
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Pair pair = (Pair)it.next();
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            writer.memberValuePair(pair.name);
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            pair.value.write(writer);
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if the given object represents the same annotation
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * as this object.  The equality test checks the member values.
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean equals(Object obj) {
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (obj == this)
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return true;
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (obj == null || obj instanceof Annotation == false)
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return false;
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Annotation other = (Annotation) obj;
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (getTypeName().equals(other.getTypeName()) == false)
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return false;
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LinkedHashMap otherMembers = other.members;
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (members == otherMembers)
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return true;
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (members == null)
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return otherMembers == null;
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (otherMembers == null)
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return false;
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return members.equals(otherMembers);
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
348