001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018package org.apache.bcel.generic; 019 020import java.io.DataInput; 021import java.io.DataOutputStream; 022import java.io.IOException; 023 024import org.apache.bcel.classfile.AnnotationElementValue; 025import org.apache.bcel.classfile.AnnotationEntry; 026import org.apache.bcel.classfile.ArrayElementValue; 027import org.apache.bcel.classfile.ClassElementValue; 028import org.apache.bcel.classfile.ElementValue; 029import org.apache.bcel.classfile.EnumElementValue; 030import org.apache.bcel.classfile.SimpleElementValue; 031 032/** 033 * @since 6.0 034 */ 035public abstract class ElementValueGen { 036 public static final int STRING = 's'; 037 038 public static final int ENUM_CONSTANT = 'e'; 039 040 public static final int CLASS = 'c'; 041 042 public static final int ANNOTATION = '@'; 043 044 public static final int ARRAY = '['; 045 046 public static final int PRIMITIVE_INT = 'I'; 047 048 public static final int PRIMITIVE_BYTE = 'B'; 049 050 public static final int PRIMITIVE_CHAR = 'C'; 051 052 public static final int PRIMITIVE_DOUBLE = 'D'; 053 054 public static final int PRIMITIVE_FLOAT = 'F'; 055 056 public static final int PRIMITIVE_LONG = 'J'; 057 058 public static final int PRIMITIVE_SHORT = 'S'; 059 060 public static final int PRIMITIVE_BOOLEAN = 'Z'; 061 062 /** 063 * Creates an (modifiable) ElementValueGen copy of an (immutable) ElementValue - constant pool is assumed correct. 064 */ 065 public static ElementValueGen copy(final ElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { 066 switch (value.getElementValueType()) { 067 case 'B': // byte 068 case 'C': // char 069 case 'D': // double 070 case 'F': // float 071 case 'I': // int 072 case 'J': // long 073 case 'S': // short 074 case 'Z': // boolean 075 case 's': // String 076 return new SimpleElementValueGen((SimpleElementValue) value, cpool, copyPoolEntries); 077 case 'e': // Enum constant 078 return new EnumElementValueGen((EnumElementValue) value, cpool, copyPoolEntries); 079 case '@': // Annotation 080 return new AnnotationElementValueGen((AnnotationElementValue) value, cpool, copyPoolEntries); 081 case '[': // Array 082 return new ArrayElementValueGen((ArrayElementValue) value, cpool, copyPoolEntries); 083 case 'c': // Class 084 return new ClassElementValueGen((ClassElementValue) value, cpool, copyPoolEntries); 085 default: 086 throw new UnsupportedOperationException("Not implemented yet! (" + value.getElementValueType() + ")"); 087 } 088 } 089 090 public static ElementValueGen readElementValue(final DataInput dis, final ConstantPoolGen cpGen) throws IOException { 091 final int type = dis.readUnsignedByte(); 092 switch (type) { 093 case 'B': // byte 094 return new SimpleElementValueGen(PRIMITIVE_BYTE, dis.readUnsignedShort(), cpGen); 095 case 'C': // char 096 return new SimpleElementValueGen(PRIMITIVE_CHAR, dis.readUnsignedShort(), cpGen); 097 case 'D': // double 098 return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis.readUnsignedShort(), cpGen); 099 case 'F': // float 100 return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis.readUnsignedShort(), cpGen); 101 case 'I': // int 102 return new SimpleElementValueGen(PRIMITIVE_INT, dis.readUnsignedShort(), cpGen); 103 case 'J': // long 104 return new SimpleElementValueGen(PRIMITIVE_LONG, dis.readUnsignedShort(), cpGen); 105 case 'S': // short 106 return new SimpleElementValueGen(PRIMITIVE_SHORT, dis.readUnsignedShort(), cpGen); 107 case 'Z': // boolean 108 return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis.readUnsignedShort(), cpGen); 109 case 's': // String 110 return new SimpleElementValueGen(STRING, dis.readUnsignedShort(), cpGen); 111 case 'e': // Enum constant 112 return new EnumElementValueGen(dis.readUnsignedShort(), dis.readUnsignedShort(), cpGen); 113 case 'c': // Class 114 return new ClassElementValueGen(dis.readUnsignedShort(), cpGen); 115 case '@': // Annotation 116 // TODO: isRuntimeVisible ?????????? 117 // FIXME 118 return new AnnotationElementValueGen(ANNOTATION, new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen.getConstantPool(), true), cpGen, false), 119 cpGen); 120 case '[': // Array 121 final int numArrayVals = dis.readUnsignedShort(); 122 final ElementValue[] evalues = new ElementValue[numArrayVals]; 123 for (int j = 0; j < numArrayVals; j++) { 124 evalues[j] = ElementValue.readElementValue(dis, cpGen.getConstantPool()); 125 } 126 return new ArrayElementValueGen(ARRAY, evalues, cpGen); 127 default: 128 throw new IllegalArgumentException("Unexpected element value kind in annotation: " + type); 129 } 130 } 131 132 /** 133 * @deprecated (since 6.0) will be made private and final; do not access directly, use getter 134 */ 135 @Deprecated 136 protected int type; 137 138 /** 139 * @deprecated (since 6.0) will be made private and final; do not access directly, use getter 140 */ 141 @Deprecated 142 protected ConstantPoolGen cpGen; 143 144 protected ElementValueGen(final int type, final ConstantPoolGen cpGen) { 145 this.type = type; 146 this.cpGen = cpGen; 147 } 148 149 public abstract void dump(DataOutputStream dos) throws IOException; 150 151 protected ConstantPoolGen getConstantPool() { 152 return cpGen; 153 } 154 155 /** 156 * Subtypes return an immutable variant of the ElementValueGen 157 */ 158 public abstract ElementValue getElementValue(); 159 160 public int getElementValueType() { 161 return type; 162 } 163 164 public abstract String stringifyValue(); 165}