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