    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 *   https://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019package org.apache.bcel.generic;
    020
    021import java.io.DataOutputStream;
    022import java.io.IOException;
    023
    024import org.apache.bcel.classfile.ConstantDouble;
    025import org.apache.bcel.classfile.ConstantFloat;
    026import org.apache.bcel.classfile.ConstantInteger;
    027import org.apache.bcel.classfile.ConstantLong;
    028import org.apache.bcel.classfile.ConstantUtf8;
    029import org.apache.bcel.classfile.ElementValue;
    030import org.apache.bcel.classfile.SimpleElementValue;
    031
    032/**
    033 * Generates simple element values in annotations.
    034 *
    035 * @since 6.0
    036 */
    037public class SimpleElementValueGen extends ElementValueGen {
    038    // For primitive types and string type, this points to the value entry in
    039    // the cpGen
    040    // For 'class' this points to the class entry in the cpGen
    041    private final int idx;
    042
    043    public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final boolean value) {
    044        super(type, cpGen);
    045        if (value) {
    046            idx = getConstantPool().addInteger(1);
    047        } else {
    048            idx = getConstantPool().addInteger(0);
    049        }
    050    }
    051
    052    public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final byte value) {
    053        super(type, cpGen);
    054        idx = getConstantPool().addInteger(value);
    055    }
    056
    057    public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final char value) {
    058        super(type, cpGen);
    059        idx = getConstantPool().addInteger(value);
    060    }
    061
    062    public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final double value) {
    063        super(type, cpGen);
    064        idx = getConstantPool().addDouble(value);
    065    }
    066
    067    public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final float value) {
    068        super(type, cpGen);
    069        idx = getConstantPool().addFloat(value);
    070    }
    071
    072    public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final int value) {
    073        super(type, cpGen);
    074        idx = getConstantPool().addInteger(value);
    075    }
    076
    077    public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final long value) {
    078        super(type, cpGen);
    079        idx = getConstantPool().addLong(value);
    080    }
    081
    082    public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final short value) {
    083        super(type, cpGen);
    084        idx = getConstantPool().addInteger(value);
    085    }
    086
    087    public SimpleElementValueGen(final int type, final ConstantPoolGen cpGen, final String value) {
    088        super(type, cpGen);
    089        idx = getConstantPool().addUtf8(value);
    090    }
    091
    092    // ctors for each supported type... type could be inferred but for now lets
    093    // force it to be passed
    094
    095    /**
    096     * Protected ctor used for deserialization, doesn't *put* an entry in the constant pool, assumes the one at the supplied
    097     * index is correct.
    098     */
    099    protected SimpleElementValueGen(final int type, final int idx, final ConstantPoolGen cpGen) {
    100        super(type, cpGen);
    101        this.idx = idx;
    102    }
    103
    104    /**
    105     * The boolean controls whether we copy info from the 'old' constant pool to the 'new'. You need to use this ctor if the
    106     * annotation is being copied from one file to another.
    107     */
    108    public SimpleElementValueGen(final SimpleElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
    109        super(value.getElementValueType(), cpool);
    110        if (!copyPoolEntries) {
    111            // J5ASSERT: Could assert value.stringifyValue() is the same as
    112            // cpool.getConstant(SimpleElementValuevalue.getIndex())
    113            idx = value.getIndex();
    114        } else {
    115            switch (value.getElementValueType()) {
    116            case STRING:
    117                idx = cpool.addUtf8(value.getValueString());
    118                break;
    119            case PRIMITIVE_INT:
    120                idx = cpool.addInteger(value.getValueInt());
    121                break;
    122            case PRIMITIVE_BYTE:
    123                idx = cpool.addInteger(value.getValueByte());
    124                break;
    125            case PRIMITIVE_CHAR:
    126                idx = cpool.addInteger(value.getValueChar());
    127                break;
    128            case PRIMITIVE_LONG:
    129                idx = cpool.addLong(value.getValueLong());
    130                break;
    131            case PRIMITIVE_FLOAT:
    132                idx = cpool.addFloat(value.getValueFloat());
    133                break;
    134            case PRIMITIVE_DOUBLE:
    135                idx = cpool.addDouble(value.getValueDouble());
    136                break;
    137            case PRIMITIVE_BOOLEAN:
    138                if (value.getValueBoolean()) {
    139                    idx = cpool.addInteger(1);
    140                } else {
    141                    idx = cpool.addInteger(0);
    142                }
    143                break;
    144            case PRIMITIVE_SHORT:
    145                idx = cpool.addInteger(value.getValueShort());
    146                break;
    147            default:
    148                throw new IllegalArgumentException("SimpleElementValueGen class does not know how to copy this type " + super.getElementValueType());
    149            }
    150        }
    151    }
    152
    153    @Override
    154    public void dump(final DataOutputStream dos) throws IOException {
    155        dos.writeByte(super.getElementValueType()); // u1 kind of value
    156        switch (super.getElementValueType()) {
    157        case PRIMITIVE_INT:
    158        case PRIMITIVE_BYTE:
    159        case PRIMITIVE_CHAR:
    160        case PRIMITIVE_FLOAT:
    161        case PRIMITIVE_LONG:
    162        case PRIMITIVE_BOOLEAN:
    163        case PRIMITIVE_SHORT:
    164        case PRIMITIVE_DOUBLE:
    165        case STRING:
    166            dos.writeShort(idx);
    167            break;
    168        default:
    169            throw new IllegalStateException("SimpleElementValueGen doesn't know how to write out type " + super.getElementValueType());
    170        }
    171    }
    172
    173    /**
    174     * Return immutable variant
    175     */
    176    @Override
    177    public ElementValue getElementValue() {
    178        return new SimpleElementValue(super.getElementValueType(), idx, getConstantPool().getConstantPool());
    179    }
    180
    181    public int getIndex() {
    182        return idx;
    183    }
    184
    185    public int getValueInt() {
    186        if (super.getElementValueType() != PRIMITIVE_INT) {
    187            throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
    188        }
    189        final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx);
    190        return c.getBytes();
    191    }
    192
    193    public String getValueString() {
    194        if (super.getElementValueType() != STRING) {
    195            throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
    196        }
    197        final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx);
    198        return c.getBytes();
    199    }
    200
    201    // Whatever kind of value it is, return it as a string
    202    @Override
    203    public String stringifyValue() {
    204        switch (super.getElementValueType()) {
    205        case PRIMITIVE_INT:
    206            final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx);
    207            return Integer.toString(c.getBytes());
    208        case PRIMITIVE_LONG:
    209            final ConstantLong j = (ConstantLong) getConstantPool().getConstant(idx);
    210            return Long.toString(j.getBytes());
    211        case PRIMITIVE_DOUBLE:
    212            final ConstantDouble d = (ConstantDouble) getConstantPool().getConstant(idx);
    213            return Double.toString(d.getBytes());
    214        case PRIMITIVE_FLOAT:
    215            final ConstantFloat f = (ConstantFloat) getConstantPool().getConstant(idx);
    216            return Float.toString(f.getBytes());
    217        case PRIMITIVE_SHORT:
    218            final ConstantInteger s = (ConstantInteger) getConstantPool().getConstant(idx);
    219            return Integer.toString(s.getBytes());
    220        case PRIMITIVE_BYTE:
    221            final ConstantInteger b = (ConstantInteger) getConstantPool().getConstant(idx);
    222            return Integer.toString(b.getBytes());
    223        case PRIMITIVE_CHAR:
    224            final ConstantInteger ch = (ConstantInteger) getConstantPool().getConstant(idx);
    225            return Integer.toString(ch.getBytes());
    226        case PRIMITIVE_BOOLEAN:
    227            final ConstantInteger bo = (ConstantInteger) getConstantPool().getConstant(idx);
    228            if (bo.getBytes() == 0) {
    229                return "false";
    230            }
    231            return "true";
    232        case STRING:
    233            final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx);
    234            return cu8.getBytes();
    235        default:
    236            throw new IllegalStateException("SimpleElementValueGen class does not know how to stringify type " + super.getElementValueType());
    237        }
    238    }
    239}