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 Sigalpackage javassist.bytecode.annotation;
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool;
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ConstPool;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.Array;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.Method;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Array member.
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author Shigeru Chiba
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class ArrayMemberValue extends MemberValue {
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    MemberValue type;
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    MemberValue[] values;
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs an array.  The initial value or type are not specified.
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public ArrayMemberValue(ConstPool cp) {
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super('[', cp);
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        type = null;
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        values = null;
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs an array.  The initial value is not specified.
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param t         the type of the array elements.
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public ArrayMemberValue(MemberValue t, ConstPool cp) {
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super('[', cp);
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        type = t;
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        values = null;
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    Object getValue(ClassLoader cl, ClassPool cp, Method method)
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws ClassNotFoundException
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (values == null)
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new ClassNotFoundException(
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        "no array elements found: " + method.getName());
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int size = values.length;
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Class clazz;
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (type == null) {
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            clazz = method.getReturnType().getComponentType();
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (clazz == null || size > 0)
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new ClassNotFoundException("broken array type: "
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                 + method.getName());
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            clazz = type.getType(cl);
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Object a = Array.newInstance(clazz, size);
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < size; i++)
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Array.set(a, i, values[i].getValue(cl, cp, method));
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return a;
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    Class getType(ClassLoader cl) throws ClassNotFoundException {
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (type == null)
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new ClassNotFoundException("no array type specified");
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Object a = Array.newInstance(type.getType(cl), 0);
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return a.getClass();
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains the type of the elements.
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return null if the type is not specified.
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public MemberValue getType() {
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return type;
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains the elements of the array.
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public MemberValue[] getValue() {
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return values;
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets the elements of the array.
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setValue(MemberValue[] elements) {
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        values = elements;
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (elements != null && elements.length > 0)
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            type = elements[0];
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Obtains the string representation of this object.
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String toString() {
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        StringBuffer buf = new StringBuffer("{");
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (values != null) {
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < values.length; i++) {
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                buf.append(values[i].toString());
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (i + 1 < values.length)
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    buf.append(", ");
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        buf.append("}");
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return buf.toString();
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Writes the value.
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void write(AnnotationsWriter writer) throws IOException {
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int num = values.length;
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        writer.arrayValue(num);
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < num; ++i)
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            values[i].write(writer);
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Accepts a visitor.
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void accept(MemberValueVisitor visitor) {
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        visitor.visitArrayMemberValue(this);
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
145