/******************************************************************************* * Copyright (c) 1998, 2016 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.tools.workbench.utility.classfile; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import org.eclipse.persistence.tools.workbench.utility.ClassTools; import org.eclipse.persistence.tools.workbench.utility.classfile.tools.ClassFileDataInputStream; import org.eclipse.persistence.tools.workbench.utility.io.IndentingPrintWriter; /** * This class models a class file constant: * u1 tag; * u1[] info; * * See "The Java Virtual Machine Specification" Chapter 4. */ public abstract class Constant { /** the pool the constant is in */ private ConstantPool pool; /** the constant's tag, which determines its type */ private byte tag; /** constants defined in "The Java Virtual Machine Specification" */ public static final byte CONSTANT_Class = 7; public static final byte CONSTANT_Fieldref = 9; public static final byte CONSTANT_Methodref = 10; public static final byte CONSTANT_InterfaceMethodref = 11; public static final byte CONSTANT_String = 8; public static final byte CONSTANT_Integer = 3; public static final byte CONSTANT_Float = 4; public static final byte CONSTANT_Long = 5; public static final byte CONSTANT_Double = 6; public static final byte CONSTANT_NameAndType = 12; public static final byte CONSTANT_Utf8 = 1; public static final byte CONSTANT_MethodHandle = 15; public static final byte CONSTANT_MethodType = 16; public static final byte CONSTANT_InvokeDynamic = 18; /** * Return a null class file constant. */ static Constant nullConstant(ConstantPool pool, ClassFileDataInputStream stream) throws IOException { return new NullConstant(pool, (byte) 0, stream); } /** * Construct a class file constant from the specified stream * of byte codes. */ static Constant buildConstant(ConstantPool pool, ClassFileDataInputStream stream) throws IOException { return buildConstant(pool, stream.readU1(), stream); } private static Constant buildConstant(ConstantPool pool, byte tag, ClassFileDataInputStream stream) throws IOException { switch (tag) { case CONSTANT_Utf8: return new UTF8Constant(pool, tag, stream); case CONSTANT_Integer: return new IntegerConstant(pool, tag, stream); case CONSTANT_Float: return new FloatConstant(pool, tag, stream); case CONSTANT_Long: return new LongConstant(pool, tag, stream); case CONSTANT_Double: return new DoubleConstant(pool, tag, stream); case CONSTANT_Class: return new ClassConstant(pool, tag, stream); case CONSTANT_String: return new StringConstant(pool, tag, stream); case CONSTANT_Fieldref: return new FieldRefConstant(pool, tag, stream); case CONSTANT_Methodref: return new MethodRefConstant(pool, tag, stream); case CONSTANT_InterfaceMethodref: return new InterfaceMethodRefConstant(pool, tag, stream); case CONSTANT_NameAndType: return new NameAndTypeConstant(pool, tag, stream); case CONSTANT_MethodHandle: return new MethodHandleConstant(pool, tag, stream); case CONSTANT_MethodType: return new MethodTypeConstant(pool, tag, stream); case CONSTANT_InvokeDynamic: return new InvokeDynamicConstant(pool, tag, stream); default: throw new IOException("Invalid constant tag: " + tag); } } /** * Construct a class file constant from the specified stream * of byte codes. */ Constant(ConstantPool pool, byte tag, ClassFileDataInputStream stream) throws IOException { super(); this.pool = pool; this.tag = tag; this.initialize(stream); } abstract void initialize(ClassFileDataInputStream stream) throws IOException; public String displayString() { StringWriter sw = new StringWriter(100); IndentingPrintWriter writer = new IndentingPrintWriter(sw); this.displayStringOn(writer); return sw.toString(); } public void displayStringOn(IndentingPrintWriter writer) { writer.print("tag: "); writer.print(this.tag); writer.print(" ("); writer.print(this.description()); writer.print(")"); } public abstract String description(); public void printFieldInitializationClauseOn(PrintWriter writer) { throw new UnsupportedOperationException(this.getClass().getName()); } public ConstantPool getPool() { return this.pool; } public byte getTag() { return this.tag; } public String utf8String(short index) { return this.pool.getUTF8String(index); } /** * "In retrospect, making 8-byte constants take * two constant pool entries was a poor choice." */ boolean consumesTwoPoolEntries() { return false; } /** * Return the value of the constant. */ public abstract Object value(); public abstract void accept(Visitor visitor); @Override public final String toString() { StringBuffer sb = new StringBuffer(); sb.append(ClassTools.shortClassNameForObject(this)); sb.append('('); this.toString(sb); sb.append(')'); return sb.toString(); } void toString(StringBuffer sb) { sb.append(this.value()); } }