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{ 037 /** 038 * @deprecated (since 6.0) will be made private and final; do not access directly, use getter 039 */ 040 @Deprecated 041 protected int type; 042 043 /** 044 * @deprecated (since 6.0) will be made private and final; do not access directly, use getter 045 */ 046 @Deprecated 047 protected ConstantPoolGen cpGen; 048 049 protected ElementValueGen(final int type, final ConstantPoolGen cpGen) 050 { 051 this.type = type; 052 this.cpGen = cpGen; 053 } 054 055 /** 056 * Subtypes return an immutable variant of the ElementValueGen 057 */ 058 public abstract ElementValue getElementValue(); 059 060 public int getElementValueType() 061 { 062 return type; 063 } 064 065 public abstract String stringifyValue(); 066 067 public abstract void dump(DataOutputStream dos) throws IOException; 068 069 public static final int STRING = 's'; 070 071 public static final int ENUM_CONSTANT = 'e'; 072 073 public static final int CLASS = 'c'; 074 075 public static final int ANNOTATION = '@'; 076 077 public static final int ARRAY = '['; 078 079 public static final int PRIMITIVE_INT = 'I'; 080 081 public static final int PRIMITIVE_BYTE = 'B'; 082 083 public static final int PRIMITIVE_CHAR = 'C'; 084 085 public static final int PRIMITIVE_DOUBLE = 'D'; 086 087 public static final int PRIMITIVE_FLOAT = 'F'; 088 089 public static final int PRIMITIVE_LONG = 'J'; 090 091 public static final int PRIMITIVE_SHORT = 'S'; 092 093 public static final int PRIMITIVE_BOOLEAN = 'Z'; 094 095 public static ElementValueGen readElementValue(final DataInput dis, 096 final ConstantPoolGen cpGen) throws IOException 097 { 098 final int type = dis.readUnsignedByte(); 099 switch (type) 100 { 101 case 'B': // byte 102 return new SimpleElementValueGen(PRIMITIVE_BYTE, dis 103 .readUnsignedShort(), cpGen); 104 case 'C': // char 105 return new SimpleElementValueGen(PRIMITIVE_CHAR, dis 106 .readUnsignedShort(), cpGen); 107 case 'D': // double 108 return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis 109 .readUnsignedShort(), cpGen); 110 case 'F': // float 111 return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis 112 .readUnsignedShort(), cpGen); 113 case 'I': // int 114 return new SimpleElementValueGen(PRIMITIVE_INT, dis 115 .readUnsignedShort(), cpGen); 116 case 'J': // long 117 return new SimpleElementValueGen(PRIMITIVE_LONG, dis 118 .readUnsignedShort(), cpGen); 119 case 'S': // short 120 return new SimpleElementValueGen(PRIMITIVE_SHORT, dis 121 .readUnsignedShort(), cpGen); 122 case 'Z': // boolean 123 return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis 124 .readUnsignedShort(), cpGen); 125 case 's': // String 126 return new SimpleElementValueGen(STRING, dis.readUnsignedShort(), 127 cpGen); 128 case 'e': // Enum constant 129 return new EnumElementValueGen(dis.readUnsignedShort(), dis 130 .readUnsignedShort(), cpGen); 131 case 'c': // Class 132 return new ClassElementValueGen(dis.readUnsignedShort(), cpGen); 133 case '@': // Annotation 134 // TODO: isRuntimeVisible ?????????? 135 // FIXME 136 return new AnnotationElementValueGen(ANNOTATION, 137 new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen 138 .getConstantPool(), true), cpGen, false), cpGen); 139 case '[': // Array 140 final int numArrayVals = dis.readUnsignedShort(); 141 final ElementValue[] evalues = new ElementValue[numArrayVals]; 142 for (int j = 0; j < numArrayVals; j++) 143 { 144 evalues[j] = ElementValue.readElementValue(dis, cpGen 145 .getConstantPool()); 146 } 147 return new ArrayElementValueGen(ARRAY, evalues, cpGen); 148 default: 149 throw new RuntimeException("Unexpected element value kind in annotation: " + type); 150 } 151 } 152 153 protected ConstantPoolGen getConstantPool() 154 { 155 return cpGen; 156 } 157 158 /** 159 * Creates an (modifiable) ElementValueGen copy of an (immutable) 160 * ElementValue - constant pool is assumed correct. 161 */ 162 public static ElementValueGen copy(final ElementValue value, 163 final ConstantPoolGen cpool, final boolean copyPoolEntries) 164 { 165 switch (value.getElementValueType()) 166 { 167 case 'B': // byte 168 case 'C': // char 169 case 'D': // double 170 case 'F': // float 171 case 'I': // int 172 case 'J': // long 173 case 'S': // short 174 case 'Z': // boolean 175 case 's': // String 176 return new SimpleElementValueGen((SimpleElementValue) value, cpool, 177 copyPoolEntries); 178 case 'e': // Enum constant 179 return new EnumElementValueGen((EnumElementValue) value, cpool, 180 copyPoolEntries); 181 case '@': // Annotation 182 return new AnnotationElementValueGen( 183 (AnnotationElementValue) value, cpool, copyPoolEntries); 184 case '[': // Array 185 return new ArrayElementValueGen((ArrayElementValue) value, cpool, 186 copyPoolEntries); 187 case 'c': // Class 188 return new ClassElementValueGen((ClassElementValue) value, cpool, 189 copyPoolEntries); 190 default: 191 throw new RuntimeException("Not implemented yet! (" + value.getElementValueType() + ")"); 192 } 193 } 194}