ElementValueGen.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *  Unless required by applicable law or agreed to in writing, software
  12.  *  distributed under the License is distributed on an "AS IS" BASIS,
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *  See the License for the specific language governing permissions and
  15.  *  limitations under the License.
  16.  */
  17. package org.apache.bcel.generic;

  18. import java.io.DataInput;
  19. import java.io.DataOutputStream;
  20. import java.io.IOException;

  21. import org.apache.bcel.classfile.AnnotationElementValue;
  22. import org.apache.bcel.classfile.AnnotationEntry;
  23. import org.apache.bcel.classfile.ArrayElementValue;
  24. import org.apache.bcel.classfile.ClassElementValue;
  25. import org.apache.bcel.classfile.ElementValue;
  26. import org.apache.bcel.classfile.EnumElementValue;
  27. import org.apache.bcel.classfile.SimpleElementValue;

  28. /**
  29.  * @since 6.0
  30.  */
  31. public abstract class ElementValueGen {
  32.     public static final int STRING = 's';

  33.     public static final int ENUM_CONSTANT = 'e';

  34.     public static final int CLASS = 'c';

  35.     public static final int ANNOTATION = '@';

  36.     public static final int ARRAY = '[';

  37.     public static final int PRIMITIVE_INT = 'I';

  38.     public static final int PRIMITIVE_BYTE = 'B';

  39.     public static final int PRIMITIVE_CHAR = 'C';

  40.     public static final int PRIMITIVE_DOUBLE = 'D';

  41.     public static final int PRIMITIVE_FLOAT = 'F';

  42.     public static final int PRIMITIVE_LONG = 'J';

  43.     public static final int PRIMITIVE_SHORT = 'S';

  44.     public static final int PRIMITIVE_BOOLEAN = 'Z';

  45.     /**
  46.      * Creates an (modifiable) ElementValueGen copy of an (immutable) ElementValue - constant pool is assumed correct.
  47.      */
  48.     public static ElementValueGen copy(final ElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
  49.         switch (value.getElementValueType()) {
  50.         case 'B': // byte
  51.         case 'C': // char
  52.         case 'D': // double
  53.         case 'F': // float
  54.         case 'I': // int
  55.         case 'J': // long
  56.         case 'S': // short
  57.         case 'Z': // boolean
  58.         case 's': // String
  59.             return new SimpleElementValueGen((SimpleElementValue) value, cpool, copyPoolEntries);
  60.         case 'e': // Enum constant
  61.             return new EnumElementValueGen((EnumElementValue) value, cpool, copyPoolEntries);
  62.         case '@': // Annotation
  63.             return new AnnotationElementValueGen((AnnotationElementValue) value, cpool, copyPoolEntries);
  64.         case '[': // Array
  65.             return new ArrayElementValueGen((ArrayElementValue) value, cpool, copyPoolEntries);
  66.         case 'c': // Class
  67.             return new ClassElementValueGen((ClassElementValue) value, cpool, copyPoolEntries);
  68.         default:
  69.             throw new UnsupportedOperationException("Not implemented yet! (" + value.getElementValueType() + ")");
  70.         }
  71.     }

  72.     public static ElementValueGen readElementValue(final DataInput dis, final ConstantPoolGen cpGen) throws IOException {
  73.         final int type = dis.readUnsignedByte();
  74.         switch (type) {
  75.         case 'B': // byte
  76.             return new SimpleElementValueGen(PRIMITIVE_BYTE, dis.readUnsignedShort(), cpGen);
  77.         case 'C': // char
  78.             return new SimpleElementValueGen(PRIMITIVE_CHAR, dis.readUnsignedShort(), cpGen);
  79.         case 'D': // double
  80.             return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis.readUnsignedShort(), cpGen);
  81.         case 'F': // float
  82.             return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis.readUnsignedShort(), cpGen);
  83.         case 'I': // int
  84.             return new SimpleElementValueGen(PRIMITIVE_INT, dis.readUnsignedShort(), cpGen);
  85.         case 'J': // long
  86.             return new SimpleElementValueGen(PRIMITIVE_LONG, dis.readUnsignedShort(), cpGen);
  87.         case 'S': // short
  88.             return new SimpleElementValueGen(PRIMITIVE_SHORT, dis.readUnsignedShort(), cpGen);
  89.         case 'Z': // boolean
  90.             return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis.readUnsignedShort(), cpGen);
  91.         case 's': // String
  92.             return new SimpleElementValueGen(STRING, dis.readUnsignedShort(), cpGen);
  93.         case 'e': // Enum constant
  94.             return new EnumElementValueGen(dis.readUnsignedShort(), dis.readUnsignedShort(), cpGen);
  95.         case 'c': // Class
  96.             return new ClassElementValueGen(dis.readUnsignedShort(), cpGen);
  97.         case '@': // Annotation
  98.             // TODO: isRuntimeVisible ??????????
  99.             // FIXME
  100.             return new AnnotationElementValueGen(ANNOTATION, new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen.getConstantPool(), true), cpGen, false),
  101.                 cpGen);
  102.         case '[': // Array
  103.             final int numArrayVals = dis.readUnsignedShort();
  104.             final ElementValue[] evalues = new ElementValue[numArrayVals];
  105.             for (int j = 0; j < numArrayVals; j++) {
  106.                 evalues[j] = ElementValue.readElementValue(dis, cpGen.getConstantPool());
  107.             }
  108.             return new ArrayElementValueGen(ARRAY, evalues, cpGen);
  109.         default:
  110.             throw new IllegalArgumentException("Unexpected element value kind in annotation: " + type);
  111.         }
  112.     }

  113.     /**
  114.      * @deprecated (since 6.0) will be made private and final; do not access directly, use getter
  115.      */
  116.     @Deprecated
  117.     protected int type;

  118.     /**
  119.      * @deprecated (since 6.0) will be made private and final; do not access directly, use getter
  120.      */
  121.     @Deprecated
  122.     protected ConstantPoolGen cpGen;

  123.     protected ElementValueGen(final int type, final ConstantPoolGen cpGen) {
  124.         this.type = type;
  125.         this.cpGen = cpGen;
  126.     }

  127.     public abstract void dump(DataOutputStream dos) throws IOException;

  128.     protected ConstantPoolGen getConstantPool() {
  129.         return cpGen;
  130.     }

  131.     /**
  132.      * Subtypes return an immutable variant of the ElementValueGen
  133.      */
  134.     public abstract ElementValue getElementValue();

  135.     public int getElementValueType() {
  136.         return type;
  137.     }

  138.     public abstract String stringifyValue();
  139. }