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