You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/05/22 19:55:54 UTC
svn commit: r171351 [5/16] - in /incubator/jdo/trunk/enhancer20: ./ src/
src/conf/ src/java/ src/java/org/ src/java/org/apache/
src/java/org/apache/jdo/ src/java/org/apache/jdo/enhancer/
src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/enhancer/
src/java/org/apache/jdo/impl/enhancer/classfile/
src/java/org/apache/jdo/impl/enhancer/core/
src/java/org/apache/jdo/impl/enhancer/generator/
src/java/org/apache/jdo/impl/enhancer/meta/
src/java/org/apache/jdo/impl/enhancer/meta/model/
src/java/org/apache/jdo/impl/enhancer/meta/prop/
src/java/org/apache/jdo/impl/enhancer/meta/util/
src/java/org/apache/jdo/impl/enhancer/util/ test/ test/sempdept/
test/sempdept/src/ test/sempdept/src/empdept/
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ConstantPool.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ConstantPool.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ConstantPool.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ConstantPool.java Sun May 22 10:55:51 2005
@@ -0,0 +1,444 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+import java.util.Vector;
+import java.util.Hashtable;
+import java.io.*;
+
+/**
+ * Constant Pool implementation - this represents the constant pool
+ * of a class in a class file.
+ */
+public class ConstantPool implements VMConstants {
+
+ /* The actual pool */
+ private Vector pool = new Vector();
+
+ /* uniqifier tables */
+ private boolean hashed = false;
+ private Hashtable utfTable = new Hashtable(11);
+ private Hashtable unicodeTable = new Hashtable(3);
+ private Hashtable stringTable = new Hashtable(11);
+ private Hashtable classTable = new Hashtable(11);
+ private Hashtable intTable = new Hashtable(3);
+ private Hashtable floatTable = new Hashtable(3);
+ private Hashtable longTable = new Hashtable(3);
+ private Hashtable doubleTable = new Hashtable(3);
+
+ private Vector methodRefTable = new Vector();
+ private Vector fieldRefTable = new Vector();
+ private Vector ifaceMethodRefTable = new Vector();
+ private Vector nameAndTypeTable = new Vector();
+
+ /* public accessors */
+
+ /**
+ * Return the number of pool entries.
+ */
+ public int nEntries() {
+ return pool.size();
+ }
+
+ /**
+ * Return the constant in the pool at the specified entry index
+ */
+ public ConstBasic constantAt (int index) {
+ return (ConstBasic) pool.elementAt(index);
+ }
+
+ /**
+ * Find or create a class constant in the pool
+ */
+ public ConstClass addClass (String className) {
+ hashConstants();
+ ConstClass c = (ConstClass) classTable.get(className);
+ if (c == null) {
+ c = new ConstClass(addUtf8(className));
+ internConstant(c);
+ }
+ return c;
+ }
+
+ /**
+ * Find or create a field constant in the pool
+ */
+ public ConstFieldRef addFieldRef (String className, String fieldName,
+ String type) {
+ hashConstants();
+ ConstFieldRef f = (ConstFieldRef)
+ searchTable(fieldRefTable, className, fieldName, type);
+
+ if (f == null) {
+ f = new ConstFieldRef (addClass(className),
+ addNameAndType(fieldName, type));
+ internConstant(f);
+ }
+ return f;
+ }
+
+ /**
+ * Find or create a method constant in the pool
+ */
+ public ConstMethodRef addMethodRef (String className, String methodName,
+ String type) {
+ hashConstants();
+ ConstMethodRef m = (ConstMethodRef)
+ searchTable(methodRefTable, className, methodName, type);
+ if (m == null) {
+ m = new ConstMethodRef (addClass(className),
+ addNameAndType(methodName, type));
+ internConstant(m);
+ }
+ return m;
+ }
+
+ /**
+ * Find or create an interface method constant in the pool
+ */
+ public ConstInterfaceMethodRef addInterfaceMethodRef (String className,
+ String methodName, String type) {
+ hashConstants();
+ ConstInterfaceMethodRef m = (ConstInterfaceMethodRef)
+ searchTable(ifaceMethodRefTable, className, methodName, type);
+ if (m == null) {
+ m = new ConstInterfaceMethodRef (addClass(className),
+ addNameAndType(methodName, type));
+ internConstant(m);
+ }
+ return m;
+ }
+
+ /**
+ * Find or create a string constant in the pool
+ */
+ public ConstString addString (String s) {
+ hashConstants();
+ ConstString cs = (ConstString) stringTable.get(s);
+ if (cs == null) {
+ cs = new ConstString(addUtf8(s));
+ internConstant(cs);
+ }
+ return cs;
+ }
+
+ /**
+ * Find or create an integer constant in the pool
+ */
+ public ConstInteger addInteger (int i) {
+ hashConstants();
+ Integer io = new Integer(i);
+ ConstInteger ci = (ConstInteger) intTable.get(io);
+ if (ci == null) {
+ ci = new ConstInteger(i);
+ internConstant(ci);
+ }
+ return ci;
+ }
+
+ /**
+ * Find or create a float constant in the pool
+ */
+ public ConstFloat addFloat (float f) {
+ hashConstants();
+ Float fo = new Float(f);
+ ConstFloat cf = (ConstFloat) floatTable.get(fo);
+ if (cf == null) {
+ cf = new ConstFloat(f);
+ internConstant(cf);
+ }
+ return cf;
+ }
+
+ /**
+ * Find or create a long constant in the pool
+ */
+ public ConstLong addLong (long l) {
+ hashConstants();
+ Long lo = new Long(l);
+ ConstLong cl = (ConstLong) longTable.get(lo);
+ if (cl == null) {
+ cl = new ConstLong(l);
+ internConstant(cl);
+ internConstant(null);
+ }
+ return cl;
+ }
+
+ /**
+ * Find or create a double constant in the pool
+ */
+ public ConstDouble addDouble (double d) {
+ hashConstants();
+ Double dobj = new Double(d);
+ ConstDouble cd = (ConstDouble) doubleTable.get(dobj);
+ if (cd == null) {
+ cd = new ConstDouble(d);
+ internConstant(cd);
+ internConstant(null);
+ }
+ return cd;
+ }
+
+ /**
+ * Find or create a name/type constant in the pool
+ */
+ public ConstNameAndType addNameAndType (String name, String type) {
+ hashConstants();
+ for (int i=0; i<nameAndTypeTable.size(); i++) {
+ ConstNameAndType nt = (ConstNameAndType) nameAndTypeTable.elementAt(i);
+ if (nt.name().asString().equals(name) &&
+ nt.signature().asString().equals(type))
+ return nt;
+ }
+
+ ConstNameAndType nt =
+ new ConstNameAndType(addUtf8(name), addUtf8(type));
+ internConstant(nt);
+ return nt;
+ }
+
+ /**
+ * Find or create a utf8 constant in the pool
+ */
+ public ConstUtf8 addUtf8 (String s) {
+ hashConstants();
+ ConstUtf8 u = (ConstUtf8) utfTable.get(s);
+ if (u == null) {
+ u = new ConstUtf8(s);
+ internConstant(u);
+ }
+ return u;
+ }
+
+ /**
+ * Find or create a unicode constant in the pool
+ * Obsolete?
+ */
+ public ConstUnicode addUnicode (String s) {
+ hashConstants();
+ ConstUnicode u = (ConstUnicode) unicodeTable.get(s);
+ if (u == null) {
+ u = new ConstUnicode(s);
+ internConstant(u);
+ }
+ return u;
+ }
+
+ /* package local methods */
+
+ ConstantPool() {
+ pool.addElement(null);
+ }
+
+ ConstantPool(DataInputStream input) throws IOException {
+ pool.addElement(null);
+ int nconstants = input.readUnsignedShort()-1;
+ while (nconstants > 0)
+ nconstants -= readConstant(input);
+
+ resolvePool();
+ }
+
+ //@olsen: added 'indent' parameter
+ void print(PrintStream out, int indent) {
+ for (int i=0; i<pool.size(); i++) {
+ ConstBasic c = constantAt(i);
+ if (c != null) {
+ ClassPrint.spaces(out, indent);
+ out.print(i);
+ out.print(": ");
+ out.println(c.toString());
+ }
+ }
+ }
+
+ //@olsen: added 'out' and 'indent' parameters
+ void summarize(PrintStream out, int indent) {
+ int stringSize = 0;
+ int nStrings = 0;
+ for (int i=0; i<pool.size(); i++) {
+ ConstBasic c = constantAt(i);
+ if (c != null && c.tag() == CONSTANTUtf8) {
+ ConstUtf8 utf8 = (ConstUtf8) c;
+ stringSize += utf8.asString().length();
+ nStrings++;
+ }
+ }
+ ClassPrint.spaces(out, indent);
+ out.println("" + nStrings + " constant pool strings totalling " +
+ stringSize + " bytes");
+ }
+
+ void write (DataOutputStream buff) throws IOException {
+ buff.writeShort(pool.size());
+ for (int i=1; i<pool.size(); i++) {
+ ConstBasic cb = (ConstBasic) pool.elementAt(i);
+ if (cb != null) {
+ buff.writeByte((byte) cb.tag());
+ cb.formatData(buff);
+ }
+ }
+ }
+
+ /* private methods */
+
+ private void resolvePool() {
+ /* resolve indexes to object references */
+ for (int i=0; i<pool.size(); i++) {
+ ConstBasic c = constantAt(i);
+ if (c != null) {
+ c.setIndex(i);
+ c.resolve(this);
+ }
+ }
+ }
+
+ private void hashConstants() {
+ if (hashed)
+ return;
+
+ /* Enter objects into the hash tables */
+ for (int j=0; j<pool.size(); j++) {
+ ConstBasic c = constantAt(j);
+ if (c != null) {
+ recordConstant(c);
+ }
+ }
+
+ hashed = true;
+ }
+
+ /* returns the number of slots used */
+ private int readConstant(DataInputStream input) throws IOException {
+ ConstBasic basic;
+ byte b = input.readByte();
+ int slots = 1;
+ switch (b) {
+ case CONSTANTUtf8:
+ basic = ConstUtf8.read(input);
+ break;
+ case CONSTANTUnicode:
+ basic = ConstUnicode.read(input);
+ break;
+ case CONSTANTInteger:
+ basic = ConstInteger.read(input);
+ break;
+ case CONSTANTFloat:
+ basic = ConstFloat.read(input);
+ break;
+ case CONSTANTLong:
+ basic = ConstLong.read(input);
+ slots = 2;
+ break;
+ case CONSTANTDouble:
+ basic = ConstDouble.read(input);
+ slots = 2;
+ break;
+ case CONSTANTClass:
+ basic = ConstClass.read(input);
+ break;
+ case CONSTANTString:
+ basic = ConstString.read(input);
+ break;
+ case CONSTANTFieldRef:
+ basic = ConstFieldRef.read(input);
+ break;
+ case CONSTANTMethodRef:
+ basic = ConstMethodRef.read(input);
+ break;
+ case CONSTANTInterfaceMethodRef:
+ basic = ConstInterfaceMethodRef.read(input);
+ break;
+ case CONSTANTNameAndType:
+ basic = ConstNameAndType.read(input);
+ break;
+ default:
+ throw new ClassFormatError("Don't know this constant type: " +
+ Integer.toString(b));
+ }
+
+ pool.addElement(basic);
+ if (slots > 1)
+ pool.addElement(null);
+ return slots;
+ }
+
+ private void internConstant (ConstBasic c) {
+ if (c != null) {
+ c.setIndex(pool.size());
+ recordConstant(c);
+ }
+ pool.addElement(c);
+ }
+
+ private void recordConstant (ConstBasic c) {
+ if (c != null) {
+ switch (c.tag()) {
+ case CONSTANTUtf8:
+ utfTable.put(((ConstUtf8)c).asString(), c);
+ break;
+ case CONSTANTUnicode:
+ unicodeTable.put(((ConstUnicode)c).asString(), c);
+ break;
+ case CONSTANTInteger:
+ intTable.put(new Integer(((ConstInteger)c).value()), c);
+ break;
+ case CONSTANTFloat:
+ floatTable.put(new Float(((ConstFloat)c).value()), c);
+ break;
+ case CONSTANTLong:
+ longTable.put(new Long(((ConstLong)c).value()), c);
+ break;
+ case CONSTANTDouble:
+ doubleTable.put(new Double(((ConstDouble)c).value()), c);
+ break;
+ case CONSTANTClass:
+ classTable.put(((ConstClass)c).asString(), c);
+ break;
+ case CONSTANTString:
+ stringTable.put(((ConstString)c).value().asString(), c);
+ break;
+ case CONSTANTFieldRef:
+ fieldRefTable.addElement(c);
+ break;
+ case CONSTANTMethodRef:
+ methodRefTable.addElement(c);
+ break;
+ case CONSTANTInterfaceMethodRef:
+ ifaceMethodRefTable.addElement(c);
+ break;
+ case CONSTANTNameAndType:
+ nameAndTypeTable.addElement(c);
+ break;
+ }
+ }
+ }
+
+ private ConstBasicMemberRef searchTable(Vector table, String cname,
+ String mname, String sig) {
+ for (int i=0; i<table.size(); i++) {
+ ConstBasicMemberRef memRef = (ConstBasicMemberRef) table.elementAt(i);
+ if (memRef.className().asString().equals(cname) &&
+ memRef.nameAndType().name().asString().equals(mname) &&
+ memRef.nameAndType().signature().asString().equals(sig))
+ return memRef;
+ }
+ return null;
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ConstantValueAttribute.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ConstantValueAttribute.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ConstantValueAttribute.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ConstantValueAttribute.java Sun May 22 10:55:51 2005
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+import java.io.*;
+import java.util.Stack;
+
+/**
+ * ConstantValueAttribute represents a constant value attribute
+ * in a class file. These attributes are used as initialization
+ * values for static fields.
+ */
+public class ConstantValueAttribute extends ClassAttribute {
+ /* The expected name of this attribute */
+ public static final String expectedAttrName = "ConstantValue";
+
+ /* The value */
+ private ConstValue constantValue;
+
+ /* public accessors */
+
+ public ConstValue value() {
+ return constantValue;
+ }
+
+ /**
+ * Construct a constant value attribute
+ */
+ public ConstantValueAttribute(ConstUtf8 attrName, ConstValue value) {
+ super(attrName);
+ constantValue = value;
+ }
+
+ /**
+ * Compares this instance with another for structural equality.
+ */
+ //@olsen: added method
+ public boolean isEqual(Stack msg, Object obj) {
+ if (!(obj instanceof ConstantValueAttribute)) {
+ msg.push("obj/obj.getClass() = "
+ + (obj == null ? null : obj.getClass()));
+ msg.push("this.getClass() = "
+ + this.getClass());
+ return false;
+ }
+ ConstantValueAttribute other = (ConstantValueAttribute)obj;
+
+ if (!super.isEqual(msg, other)) {
+ return false;
+ }
+
+ if (!this.constantValue.isEqual(msg, other.constantValue)) {
+ msg.push(String.valueOf("constantValue = "
+ + other.constantValue));
+ msg.push(String.valueOf("constantValue = "
+ + this.constantValue));
+ return false;
+ }
+ return true;
+ }
+
+ /* package local methods */
+
+ static ConstantValueAttribute read(ConstUtf8 attrName,
+ DataInputStream data, ConstantPool pool)
+ throws IOException {
+ int index = 0;
+ index = data.readUnsignedShort();
+
+ return new ConstantValueAttribute(attrName,
+ (ConstValue) pool.constantAt(index));
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeShort(attrName().getIndex());
+ out.writeInt(2);
+ out.writeShort(constantValue.getIndex());
+ }
+
+ void print(PrintStream out, int indent) {
+ ClassPrint.spaces(out, indent);
+ out.println("ConstantValue: " + constantValue.toString());
+ }
+}
+
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/Descriptor.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/Descriptor.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/Descriptor.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/Descriptor.java Sun May 22 10:55:51 2005
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+import java.util.Stack;
+import java.util.Map;
+
+//@olsen: subst: Hashtable -> Map, HashMap
+
+
+/**
+ * A collection of static methods which manipulate type descriptors
+ */
+public class Descriptor implements VMConstants {
+ /**
+ * Return the number of words of arguments to the method
+ * based on the method signature
+ */
+ public static int countMethodArgWords(String sig) {
+ if (sig.charAt(0) != '(')
+ throw new InsnError ("not a method signature");
+ int count = 0;
+ for (int idx = 1; sig.charAt(idx) != ')'; idx++) {
+ switch (sig.charAt(idx)) {
+ case 'B': /* byte */
+ case 'C': /* char */
+ case 'S': /* short */
+ case 'I': /* int */
+ case 'F': /* float */
+ case 'Z': /* boolean */
+ count++;
+ break;
+ case 'J': /* long */
+ case 'D': /* double */
+ count += 2;
+ break;
+ case 'L':
+ count++;
+ idx = sig.indexOf(';', idx);
+ break;
+ case '[':
+ count++;
+ while (sig.charAt(idx) == '[' || sig.charAt(idx) == ']')
+ idx++;
+ if (sig.charAt(idx) == 'L')
+ idx = sig.indexOf(';', idx);
+ /* else, let idx++ at loop iteration skip primitive descriptor */
+ break;
+ default:
+ throw new InsnError("missing case");
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Return the number of words of return value for the method
+ * based on the method signature
+ */
+ public static int countMethodReturnWords(String sig) {
+ int idx = sig.lastIndexOf(')') + 1;
+ if (idx == 0)
+ throw new InsnError ("not a method signature");
+ switch (sig.charAt(idx)) {
+ case 'J': /* long */
+ case 'D': /* double */
+ return 2;
+ case 'B': /* byte */
+ case 'C': /* char */
+ case 'S': /* short */
+ case 'I': /* int */
+ case 'F': /* float */
+ case 'Z': /* boolean */
+ case 'L': /* object */
+ case '[': /* array */
+ return 1;
+ case 'V': /* void */
+ return 0;
+ default:
+ throw new InsnError("missing case");
+ }
+ }
+
+ /**
+ * Return the stack descriptor for the result of a method
+ * invocation. Void return values yield "V".
+ */
+ public static String extractResultSig(String methodSig) {
+ return methodSig.substring(methodSig.indexOf(')')+1);
+ }
+
+ /**
+ * Return the stack descriptor for the arguments to a method
+ * invocation (not including any "this" argument)
+ */
+ public static String extractArgSig(String methodSig) {
+ return methodSig.substring(1, methodSig.indexOf(')'));
+ }
+
+ /**
+ * Return the reversed stack descriptor for the arguments to a method
+ * invocation (not including any "this" argument). The top of stack
+ * element will be first.
+ */
+ public static String extractReversedArgSig(String methodSig) {
+ StringBuffer buf = new StringBuffer();;
+ reverseArgSig(buf, methodSig, 1);
+ return buf.toString();
+ }
+
+ /**
+ * Given a StringBuffer, a method descriptor, and a index to the
+ * start of an argument descriptor, append the arguments to the
+ * string buffer in reverse order.
+ */
+ private static void reverseArgSig(StringBuffer buf, String methodSig,
+ int idx) {
+ char c = methodSig.charAt(idx);
+ if (c == ')')
+ return;
+ int startIdx = idx;
+
+ switch(c) {
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ case 'Z':
+ idx = idx+1;
+ break;
+ case '[':
+ while (methodSig.charAt(idx) == '[' || methodSig.charAt(idx) == ']')
+ idx++;
+ if (methodSig.charAt(idx) != 'L') {
+ idx++;
+ break;
+ }
+ /* fall through */
+ case 'L':
+ idx = methodSig.indexOf(';', idx) + 1;
+ break;
+ default:
+ throw new InsnError("bad signature char");
+ }
+
+ reverseArgSig(buf, methodSig, idx);
+ while (startIdx < idx)
+ buf.append(methodSig.charAt(startIdx++));
+ }
+
+ /**
+ * Return the number of words of a field based on its signature.
+ */
+ //@olsen: added method
+ public static int countFieldWords(String sig) {
+ if (sig == null || sig.length() < 1)
+ throw new InsnError ("not a field signature");
+ switch (sig.charAt(0)) {
+ case 'J': /* long */
+ case 'D': /* double */
+ return 2;
+ case 'B': /* byte */
+ case 'C': /* char */
+ case 'S': /* short */
+ case 'I': /* int */
+ case 'F': /* float */
+ case 'Z': /* boolean */
+ case 'L': /* object */
+ case '[': /* array */
+ return 1;
+ default:
+ throw new InsnError("missing case");
+ }
+ }
+
+ /**
+ * Return the element type for the first char in the type descriptor string.
+ */
+ //@olsen: added method
+ public static int elementType(String sig) {
+ if (sig == null || sig.length() < 1)
+ throw new InsnError ("not a value signature");
+ switch(sig.charAt(0)) {
+ case 'B':
+ return T_BOOLEAN;
+ case 'C':
+ return T_CHAR;
+ case 'Z':
+ return T_BYTE;
+ case 'S':
+ return T_SHORT;
+ case 'I':
+ return T_INT;
+ case 'J':
+ return T_LONG;
+ case 'F':
+ return T_FLOAT;
+ case 'D':
+ return T_DOUBLE;
+ case '[':
+ return TC_OBJECT;
+ case 'L':
+ return TC_OBJECT;
+ default:
+ throw new InsnError("bad signature char");
+ }
+ }
+
+ /**
+ * Return the element type descriptor char for the element type.
+ * The element type must be one of the T_ or TC_OBJECT.
+ */
+ public static String elementSig(int valueType) {
+ switch(valueType) {
+ case T_BYTE:
+ return "B";
+ case T_CHAR:
+ return "C";
+ case T_BOOLEAN:
+ return "Z";
+ case T_SHORT:
+ return "S";
+ case T_INT:
+ return "I";
+ case T_LONG:
+ return "J";
+ case T_FLOAT:
+ return "F";
+ case T_DOUBLE:
+ return "D";
+ case TC_OBJECT:
+ return "Ljava/lang/Object;";
+ default:
+ throw new InsnError("bad element type");
+ }
+ }
+
+ /**
+ * Return the number of stack words required for a value of the specified
+ * type on the operand stack.
+ */
+ public static int elementSize(int elementType) {
+ switch(elementType) {
+ case T_LONG:
+ case T_DOUBLE:
+ case T_TWOWORD:
+ return 2;
+ default:
+ return 1;
+ }
+ }
+
+ /**
+ * stackSig is a signature for a list of types on the JVM stack with the
+ * last type in the signature intended to be on the top of JVM stack.
+ * For each type in the signature, pushes an Integer objects identifying
+ * the types on top of the input Stack object.
+ */
+ public static void computeStackTypes(String stackSig, Stack stack) {
+ for (int idx = 0; idx < stackSig.length(); idx++) {
+ int tp = 0;
+ switch(stackSig.charAt(idx)) {
+ case 'B':
+ case 'C':
+ case 'Z':
+ case 'S':
+ case 'I':
+ tp = T_INT;
+ break;
+ case 'F':
+ tp = T_FLOAT;
+ break;
+ case 'J':
+ tp = T_LONG;
+ break;
+ case 'D':
+ tp = T_DOUBLE;
+ break;
+ case '?':
+ tp = T_UNKNOWN;
+ break;
+ case 'W':
+ tp = T_WORD;
+ break;
+ case 'X':
+ tp = T_TWOWORD;
+ break;
+ case 'A':
+ /* This isn't a real type, but any object refrence */
+ tp = TC_OBJECT;
+ break;
+ case '[':
+ tp = TC_OBJECT;
+ while (stackSig.charAt(idx) == '[' || stackSig.charAt(idx) == ']')
+ idx++;
+ if (stackSig.charAt(idx) != 'L')
+ break;
+ /* fall through */
+ case 'L':
+ tp = TC_OBJECT;
+ idx = stackSig.indexOf(';', idx);
+ break;
+ default:
+ throw new InsnError("bad signature char");
+ }
+ stack.push(new Integer(tp));
+ }
+ }
+
+ /**
+ * stackSig is a signature for the types on the stack with the last
+ * type in the signature on the top of stack. idx is the index of
+ * the start of a valid signature type element. Return the index of
+ * the next element (which may be past the end of the string).
+ */
+ public static int nextSigElement(String stackSig, int idx) {
+ switch(stackSig.charAt(idx)) {
+ case 'B':
+ case 'C':
+ case 'Z':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ break;
+ case '[':
+ while (stackSig.charAt(idx) == '[' || stackSig.charAt(idx) == ']')
+ idx++;
+ if (stackSig.charAt(idx) != 'L')
+ break;
+ /* fall through */
+ case 'L':
+ idx = stackSig.indexOf(';', idx);
+ break;
+ default:
+ throw new InsnError("bad signature char");
+ }
+
+ idx++;
+ return idx;
+ }
+
+ /**
+ * classTranslations contains a set of mappings of class names.
+ * For any types within the input signature which appear as keys
+ * in the translation table, change the signature to replace the
+ * original type with the translation. Return a string containing
+ * the original signature with any translations applied.
+ */
+ public static String remapTypes(String sig, Map classTranslations) {
+ /* Defer allocation of the string buffer until it's needed */
+ StringBuffer buf = null;
+
+ for (int idx = 0; idx < sig.length(); idx++) {
+ char c;
+ switch(c = sig.charAt(idx)) {
+ case '[':
+ /* An array - skip through the [] pairs, copying to buf if not null */
+ while ((c = sig.charAt(idx)) == '[' || c == ']') {
+ idx++;
+ if (buf != null)
+ buf.append(c);
+ }
+
+ /* If the next char isnt 'L', the next char is a simple type and
+ will be handled by the default 1 char translation */
+ if (sig.charAt(idx) != 'L')
+ break;
+ /* fall through to type name translation */
+ case 'L':
+ /* This is a type name */
+ idx++;
+ int endIdx = sig.indexOf(';', idx);
+ String typeName = sig.substring(idx, endIdx);
+ String mapTo = (String) classTranslations.get(typeName);
+ if (mapTo != null) {
+ /* This type needs translation - allocate the string buffer
+ now if needed and copy in all up to this type name. */
+ if (buf == null) {
+ buf = new StringBuffer(sig.length() + 20);
+ buf.append(sig.substring(0,idx-1));
+ }
+ typeName = mapTo;
+ }
+
+ if (buf != null) {
+ buf.append('L');
+ buf.append(typeName);
+ }
+ idx = endIdx;
+ c = ';';
+ break;
+ }
+
+ if (buf != null)
+ buf.append(c);
+ }
+ return (buf == null) ? sig : (buf.toString());
+ }
+
+ /**
+ * classTranslations contains a set of mappings of class names.
+ * Translate the class name (which may be an array class) according
+ * to the entries in the translation table.
+ * Return either the original string if no translation applies or
+ * else the translated string.
+ */
+ public static String translateClass(
+ String cls, Map classTranslations) {
+ if (cls.charAt(0) == '[')
+ return remapTypes(cls, classTranslations);
+ else {
+ String mapTo = (String) classTranslations.get(cls);
+ if (mapTo != null)
+ return mapTo;
+ return cls;
+ }
+ }
+
+ /**
+ * Translates a VM type field signature into a user-format signature.
+ * Just a front for the two argument overload of this method.
+ */
+ public static String userFieldSig(String vmSig) {
+ return userFieldSig(vmSig, 0);
+ }
+
+ /**
+ * Translates a VM type field signature into a user-format signature.
+ */
+ public static String userFieldSig(String vmSig, int idx) {
+ String sigElement = "";
+ int arrayDims = 0;
+ boolean moreSig = true;
+ while (moreSig) {
+ moreSig = false;
+ char c = vmSig.charAt(idx);
+ switch (c) {
+ case 'B':
+ sigElement = "byte";
+ break;
+ case 'C':
+ sigElement = "char";
+ break;
+ case 'Z':
+ sigElement = "boolean";
+ break;
+ case 'S':
+ sigElement = "short";
+ break;
+ case 'I':
+ sigElement = "int";
+ break;
+ case 'F':
+ sigElement = "float";
+ break;
+ case 'J':
+ sigElement = "long";
+ break;
+ case 'D':
+ sigElement = "double";
+ break;
+ case 'V':
+ /* void isn't really valid as a field signature but this method
+ might be useful in implementing method signature conversion and
+ void is a valid return type. */
+ sigElement = "void";
+ break;
+ case '[':
+ idx++;
+ arrayDims++;
+ moreSig = true;
+ break;
+ case 'L':
+ int nextIdx = vmSig.indexOf(';', idx);
+ sigElement = vmSig.substring(idx+1,nextIdx).replace('/','.');
+ break;
+ default:
+ throw new InsnError("bad signature char");
+ }
+ }
+
+ /* If a non-array type, we already have the answer */
+ if (arrayDims == 0)
+ return sigElement;
+
+ /* array types need a little more work */
+ StringBuffer buf = new StringBuffer(sigElement.length()
+ + 2 * arrayDims);
+ buf.append(sigElement);
+ while (arrayDims-- > 0)
+ buf.append("[]");
+
+ return buf.toString();
+ }
+
+ /**
+ * Produce a user consumable representation of a method argument list
+ * from the method signature. The return value is ignored.
+ */
+ public static String userMethodArgs(String methodSig) {
+ /* This better be a method signature */
+ if (methodSig.charAt(0) != '(')
+ throw new InsnError("Invalid method signature");
+
+ StringBuffer buf = new StringBuffer();
+
+ buf.append('(');
+
+ int idx = 1;
+ boolean firstArg = true;
+ while (methodSig.charAt(idx) != ')') {
+ if (firstArg)
+ firstArg = false;
+ else
+ buf.append(", ");
+
+ buf.append(userFieldSig(methodSig, idx));
+ idx = nextSigElement(methodSig, idx);
+ }
+
+ buf.append(')');
+ return buf.toString();
+ }
+
+ /**
+ * Produce a user consumable representation of a method result type
+ * from the method signature. The argument list is ignored.
+ */
+ //@olsen: added method
+ public static String userMethodResult(String methodSig) {
+ /* This better be a method signature */
+ if (methodSig.charAt(0) != '(')
+ throw new InsnError("Invalid method signature");
+ return userFieldSig(extractResultSig(methodSig));
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionRange.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionRange.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionRange.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionRange.java Sun May 22 10:55:51 2005
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+import java.io.*;
+import java.util.Stack;
+
+/**
+ * ExceptionRange represents a range an exception handler within
+ * a method in class file.
+ */
+public class ExceptionRange {
+ /* The start of the exception hander (inclusive) */
+ private InsnTarget excStartPC;
+
+ /* The end of the exception hander (exclusive) */
+ private InsnTarget excEndPC;
+
+ /* The exception handler code */
+ private InsnTarget excHandlerPC;
+
+ /* The exception specification */
+ private ConstClass excCatchType;
+
+ /* public accessors */
+
+ /**
+ * return the start of the exception hander (inclusive)
+ */
+ public InsnTarget startPC() {
+ return excStartPC;
+ }
+
+ /**
+ * return the end of the exception hander (exclusive)
+ */
+ public InsnTarget endPC() {
+ return excEndPC;
+ }
+
+ /**
+ * return the exception handler code
+ */
+ public InsnTarget handlerPC() {
+ return excHandlerPC;
+ }
+
+ /**
+ * return the exception specification
+ * a null return value means a catch of any (try/finally)
+ */
+ public ConstClass catchType() {
+ return excCatchType;
+ }
+
+ /**
+ * constructor
+ */
+ public ExceptionRange(InsnTarget startPC, InsnTarget endPC,
+ InsnTarget handlerPC, ConstClass catchType) {
+ excStartPC = startPC;
+ excEndPC = endPC;
+ excHandlerPC = handlerPC;
+ excCatchType = catchType;
+ }
+
+ /**
+ * Compares this instance with another for structural equality.
+ */
+ //@olsen: added method
+ public boolean isEqual(Stack msg, Object obj) {
+ if (!(obj instanceof ExceptionRange)) {
+ msg.push("obj/obj.getClass() = "
+ + (obj == null ? null : obj.getClass()));
+ msg.push("this.getClass() = "
+ + this.getClass());
+ return false;
+ }
+ ExceptionRange other = (ExceptionRange)obj;
+
+ if (!this.excStartPC.isEqual(msg, other.excStartPC)) {
+ msg.push(String.valueOf("excStartPC = "
+ + other.excStartPC));
+ msg.push(String.valueOf("excStartPC = "
+ + this.excStartPC));
+ return false;
+ }
+ if (!this.excEndPC.isEqual(msg, other.excEndPC)) {
+ msg.push(String.valueOf("excEndPC = "
+ + other.excEndPC));
+ msg.push(String.valueOf("excEndPC = "
+ + this.excEndPC));
+ return false;
+ }
+ if (!this.excHandlerPC.isEqual(msg, other.excHandlerPC)) {
+ msg.push(String.valueOf("excHandlerPC = "
+ + other.excHandlerPC));
+ msg.push(String.valueOf("excHandlerPC = "
+ + this.excHandlerPC));
+ return false;
+ }
+ if (!this.excCatchType.isEqual(msg, other.excCatchType)) {
+ msg.push(String.valueOf("excCatchType = "
+ + other.excCatchType));
+ msg.push(String.valueOf("excCatchType = "
+ + this.excCatchType));
+ return false;
+ }
+ return true;
+ }
+
+ /* package local methods */
+
+ static ExceptionRange read(DataInputStream data, CodeEnv env)
+ throws IOException {
+ InsnTarget startPC = env.getTarget(data.readUnsignedShort());
+ InsnTarget endPC = env.getTarget(data.readUnsignedShort());
+ InsnTarget handlerPC = env.getTarget(data.readUnsignedShort());
+ ConstClass catchType =
+ (ConstClass) env.pool().constantAt(data.readUnsignedShort());
+ return new ExceptionRange(startPC, endPC, handlerPC, catchType);
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeShort(excStartPC.offset());
+ out.writeShort(excEndPC.offset());
+ out.writeShort(excHandlerPC.offset());
+ out.writeShort(excCatchType == null ? 0 : excCatchType.getIndex());
+ }
+
+ void print(PrintStream out, int indent) {
+ ClassPrint.spaces(out, indent);
+ out.print("Exc Range:");
+ if (excCatchType == null)
+ out.print("any");
+ else
+ out.print("'" + excCatchType.asString() + "'");
+ out.print(" start = " + Integer.toString(excStartPC.offset()));
+ out.print(" end = " + Integer.toString(excEndPC.offset()));
+ out.println(" handle = " + Integer.toString(excHandlerPC.offset()));
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionTable.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionTable.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionTable.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionTable.java Sun May 22 10:55:51 2005
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+import java.io.*;
+import java.util.Stack;
+import java.util.Vector;
+import java.util.Enumeration;
+
+/**
+ * ExceptionTable represents the exception handlers within the code
+ * of a method.
+ */
+public class ExceptionTable {
+ /* A variable length list of ExceptionRange objects */
+ //@olsen: renamed theVector -> handlers
+ private Vector handlers = new Vector();
+
+ /* public accessors */
+
+ /**
+ * Return an enumeration of the exception handlers
+ * Each element in the enumeration is an ExceptionRange
+ */
+ public Enumeration handlers() {
+ return handlers.elements();
+ }
+
+ /**
+ * Add an exception handler to the list
+ */
+ public void addElement(ExceptionRange range) {
+ handlers.addElement(range);
+ }
+
+ public ExceptionTable() { }
+
+ /**
+ * Compares this instance with another for structural equality.
+ */
+ //@olsen: added method
+ public boolean isEqual(Stack msg, Object obj) {
+ if (!(obj instanceof ExceptionTable)) {
+ msg.push("obj/obj.getClass() = "
+ + (obj == null ? null : obj.getClass()));
+ msg.push("this.getClass() = "
+ + this.getClass());
+ return false;
+ }
+ ExceptionTable other = (ExceptionTable)obj;
+
+ if (this.handlers.size() != other.handlers.size()) {
+ msg.push("handlers.size() "
+ + String.valueOf(other.handlers.size()));
+ msg.push("handlers.size() "
+ + String.valueOf(this.handlers.size()));
+ return false;
+ }
+
+ for (int i = 0; i < handlers.size(); i++) {
+ ClassAttribute h1 = (ClassAttribute)this.handlers.get(i);
+ ClassAttribute h2 = (ClassAttribute)other.handlers.get(i);
+ if (!h1.isEqual(msg, h2)) {
+ msg.push("handlers[" + i + "] = "
+ + String.valueOf(h2));
+ msg.push("handlers[" + i + "] = "
+ + String.valueOf(h1));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* package local methods */
+
+ static ExceptionTable read(DataInputStream data, CodeEnv env)
+ throws IOException {
+ ExceptionTable excTable = new ExceptionTable();
+ int nExcepts = data.readUnsignedShort();
+ while (nExcepts-- > 0) {
+ excTable.addElement(ExceptionRange.read(data, env));
+ }
+ return excTable;
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeShort(handlers.size());
+ for (int i=0; i<handlers.size(); i++)
+ ((ExceptionRange) handlers.elementAt(i)).write(out);
+ }
+
+ void print(PrintStream out, int indent) {
+ ClassPrint.spaces(out, indent);
+ out.println("Exception Table: ");
+ for (int i=0; i<handlers.size(); i++)
+ ((ExceptionRange) handlers.elementAt(i)).print(out, indent+2);
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionsAttribute.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionsAttribute.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionsAttribute.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ExceptionsAttribute.java Sun May 22 10:55:51 2005
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+import java.io.*;
+import java.util.Stack;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Vector;
+import java.util.Enumeration;
+
+/**
+ * ExceptionsAttribute represents a method attribute in a class file
+ * listing the checked exceptions for the method.
+ */
+public class ExceptionsAttribute extends ClassAttribute {
+ public final static String expectedAttrName = "Exceptions";
+
+ /* The list of checked exceptions */
+ private Vector exceptionTable;
+
+ /* public accessors */
+
+ /**
+ * Return an enumeration of the checked exceptions
+ */
+ public Enumeration exceptions() {
+ return exceptionTable.elements();
+ }
+
+ /**
+ * Returns the vector of the checked exceptions.
+ */
+ //@olsen: added method
+ public Vector getExceptions() {
+ return exceptionTable;
+ }
+
+ /**
+ * Constructor
+ */
+ public ExceptionsAttribute(ConstUtf8 attrName, Vector excTable) {
+ super(attrName);
+ exceptionTable = excTable;
+ }
+
+ /**
+ * Convenience Constructor - for single exception
+ */
+ public ExceptionsAttribute(ConstUtf8 attrName, ConstClass exc) {
+ super(attrName);
+ exceptionTable = new Vector(1);
+ exceptionTable.addElement(exc);
+ }
+
+ /**
+ * Compares this instance with another for structural equality.
+ */
+ //@olsen: added method
+ public boolean isEqual(Stack msg, Object obj) {
+ if (!(obj instanceof ExceptionsAttribute)) {
+ msg.push("obj/obj.getClass() = "
+ + (obj == null ? null : obj.getClass()));
+ msg.push("this.getClass() = "
+ + this.getClass());
+ return false;
+ }
+ ExceptionsAttribute other = (ExceptionsAttribute)obj;
+
+ if (!super.isEqual(msg, other)) {
+ return false;
+ }
+
+ if (this.exceptionTable.size() != other.exceptionTable.size()) {
+ msg.push("exceptionTable.size() "
+ + String.valueOf(other.exceptionTable.size()));
+ msg.push("exceptionTable.size() "
+ + String.valueOf(this.exceptionTable.size()));
+ return false;
+ }
+
+ // sort exceptions by name
+ class ConstClassComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ ConstClass c1 = (ConstClass)o1;
+ ConstClass c2 = (ConstClass)o2;
+ String s1 = c1.className().asString();
+ String s2 = c2.className().asString();
+ return s1.compareTo(s2);
+ }
+ }
+ ConstClassComparator comparator = new ConstClassComparator();
+ ConstClass[] thisExceptionTable
+ = (ConstClass[])this.exceptionTable.toArray(new ConstClass[0]);
+ ConstClass[] otherExceptionTable
+ = (ConstClass[])other.exceptionTable.toArray(new ConstClass[0]);
+ Arrays.sort(thisExceptionTable, comparator);
+ Arrays.sort(otherExceptionTable, comparator);
+ for (int i = 0; i < exceptionTable.size(); i++) {
+ ConstClass c1 = thisExceptionTable[i];
+ ConstClass c2 = otherExceptionTable[i];
+ if (!c1.isEqual(msg, c2)) {
+ msg.push("exceptionTable[i] = " + String.valueOf(c2));
+ msg.push("exceptionTable[i] = " + String.valueOf(c1));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* package local methods */
+
+ static ExceptionsAttribute read(ConstUtf8 attrName,
+ DataInputStream data, ConstantPool pool)
+ throws IOException {
+ int nExcepts = data.readUnsignedShort();
+ Vector excTable = new Vector();
+ while (nExcepts-- > 0) {
+ int excIndex = data.readUnsignedShort();
+ ConstClass exc_class = null;
+ if (excIndex != 0)
+ exc_class = (ConstClass) pool.constantAt(excIndex);
+ excTable.addElement(exc_class);
+ }
+
+ return new ExceptionsAttribute(attrName, excTable);
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeShort(attrName().getIndex());
+ out.writeInt(2+2*exceptionTable.size());
+ out.writeShort(exceptionTable.size());
+ for (int i=0; i<exceptionTable.size(); i++)
+ out.writeShort(((ConstClass) exceptionTable.elementAt(i)).getIndex());
+ }
+
+ void print(PrintStream out, int indent) {
+ ClassPrint.spaces(out, indent);
+ out.print("Exceptions:");
+ for (int i=0; i<exceptionTable.size(); i++)
+ out.print(" " + ((ConstClass) exceptionTable.elementAt(i)).asString());
+ out.println();
+ }
+
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/GenericAttribute.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/GenericAttribute.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/GenericAttribute.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/GenericAttribute.java Sun May 22 10:55:51 2005
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+import java.io.*;
+import java.util.Stack;
+
+/**
+ * GenericAttribute represents a class attribute in a class file which
+ * is not recognized as any supported attribute type. These attributes
+ * are maintained, and are not modified in any way.
+ */
+
+public class GenericAttribute extends ClassAttribute {
+
+ /* The bytes of the attribute following the name */
+ byte attributeBytes[];
+
+ /* public accessors */
+
+ /**
+ * constructor
+ */
+ public GenericAttribute(ConstUtf8 attrName, byte attrBytes[]) {
+ super(attrName);
+ attributeBytes = attrBytes;
+ }
+
+ /**
+ * Compares this instance with another for structural equality.
+ */
+ //@olsen: added method
+ public boolean isEqual(Stack msg, Object obj) {
+ if (!(obj instanceof GenericAttribute)) {
+ msg.push("obj/obj.getClass() = "
+ + (obj == null ? null : obj.getClass()));
+ msg.push("this.getClass() = "
+ + this.getClass());
+ return false;
+ }
+ GenericAttribute other = (GenericAttribute)obj;
+
+ if (!super.isEqual(msg, other)) {
+ return false;
+ }
+
+ if (this.attributeBytes.length != other.attributeBytes.length) {
+ msg.push("attributeBytes.length "
+ + String.valueOf(other.attributeBytes.length));
+ msg.push("attributeBytes.length "
+ + String.valueOf(this.attributeBytes.length));
+ return false;
+ }
+
+ for (int i = 0; i < attributeBytes.length; i++) {
+ byte b1 = this.attributeBytes[i];
+ byte b2 = other.attributeBytes[i];
+ if (b1 != b2) {
+ msg.push("attributeBytes[" + i + "] = "
+ + String.valueOf(b2));
+ msg.push("attributeBytes[" + i + "] = "
+ + String.valueOf(b1));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeShort(attrName().getIndex());
+ out.writeInt(attributeBytes.length);
+ out.write(attributeBytes, 0, attributeBytes.length);
+ }
+
+ void print(PrintStream out, int indent) {
+ ClassPrint.spaces(out, indent);
+ out.println("Generic Attribute(" + attrName().asString() + "): " +
+ Integer.toString(attributeBytes.length) +
+ " in length");
+ for (int i=0; i<attributeBytes.length; i++) {
+ if ((i % 16) == 0) {
+ if (i != 0)
+ out.println();
+ out.print(i + " :");
+ }
+ out.print(" " + Integer.toString((attributeBytes[i] & 0xff), 16));
+ }
+ out.println();
+ }
+}
+
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/Insn.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/Insn.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/Insn.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/Insn.java Sun May 22 10:55:51 2005
@@ -0,0 +1,660 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+import java.io.PrintStream;
+import java.util.Stack;
+
+/**
+ * Insn is an abstract class which represents a java VM instruction in a
+ * sequence of instructions.
+ */
+abstract public class Insn implements VMConstants {
+ /* An instruction with no pc defined yet */
+ final static int NO_OFFSET = -1;
+
+ /* A special magic opcode for branch target pseudo instructions */
+ final public static int opc_target = -1;
+
+ /* The opcode of this instruction */
+ private int insnOpcode;
+
+ /* The pc of this instruction within the containing code sequence */
+ private int insnOffset = NO_OFFSET;
+
+ /* The next instruction in the code sequence */
+ private Insn nextInsn = null;
+
+ /* The previous instruction in the code sequence */
+ private Insn prevInsn = null;
+
+ /* public accessors */
+
+ /**
+ * Returns the next instruction in the code sequence
+ */
+ public Insn next() {
+ return nextInsn;
+ }
+
+ /**
+ * Returns the previous instruction in the code sequence
+ */
+ public Insn prev() {
+ return prevInsn;
+ }
+
+ /**
+ * Removes the current instruction from it's embedding sequence.
+ */
+ //@olsen: added method
+ public void remove() {
+ if (nextInsn != null)
+ nextInsn.prevInsn = prevInsn;
+
+ if (prevInsn != null)
+ prevInsn.nextInsn = nextInsn;
+
+ prevInsn = null;
+ nextInsn = null;
+ }
+
+ /**
+ * Insert the single instruction in the code sequence after this
+ * instruction.
+ * Returns the inserted instruction.
+ */
+ public Insn setNext(Insn i) {
+ if (nextInsn != null)
+ nextInsn.prevInsn = i;
+
+ if (i != null) {
+ i.nextInsn = nextInsn;
+ i.prevInsn = this;
+ }
+ nextInsn = i;
+ return i;
+ }
+
+ /**
+ * Insert an instruction sequence in the code sequence after this
+ * instruction.
+ * Returns the final instruction.
+ */
+ public Insn insert(Insn i) {
+ if (i == null)
+ return this;
+
+ Insn theNextInsn = nextInsn;
+ nextInsn = i;
+ i.prevInsn = this;
+
+ while (i.nextInsn != null)
+ i = i.nextInsn;
+ i.nextInsn = theNextInsn;
+ if (theNextInsn != null)
+ theNextInsn.prevInsn = i;
+ return i;
+ }
+
+ /**
+ * Append an instruction sequence at the end of this instruction
+ * sequence.
+ * Returns the final instruction.
+ */
+ public Insn append(Insn i) {
+ Insn thisInsn = this;
+ while (thisInsn.nextInsn != null)
+ thisInsn = thisInsn.nextInsn;
+ return thisInsn.insert(i);
+ }
+
+ /**
+ * Return the opcode for this instruction
+ */
+ public int opcode() {
+ return insnOpcode;
+ }
+
+ /**
+ * Return the offset of this instruction in the containing code sequence
+ */
+ public int offset() {
+ return insnOffset;
+ }
+
+ /**
+ * How many words of stack operands does this instruction take?
+ */
+ abstract public int nStackArgs();
+
+ /**
+ * How many words of stack results does this instruction deposit?
+ */
+ abstract public int nStackResults();
+
+ /**
+ * What are the types of the stack operands ?
+ */
+ abstract public String argTypes();
+
+ /**
+ * What are the types of the stack results?
+ */
+ abstract public String resultTypes();
+
+ /**
+ * Does this instruction branch?
+ */
+ abstract public boolean branches();
+
+ /**
+ * Mark possible branch targets
+ */
+ public void markTargets() {
+ }
+
+ /**
+ * Return the name of the operation for a given opcode
+ */
+ public static String opName(int opcode) {
+ if (opcode == opc_target)
+ return "target:";
+ if (opcode >=0 && opcode <= VMOp.ops.length)
+ return VMOp.ops[opcode].name();
+ else
+ throw new InsnError("invalid opcode for opName: " + opcode);
+ }
+
+ /* Instruction creation interfaces - these should be used for all
+ * instructions except opc_iinc, opc_tableswitch, opc_lookupswitch,
+ * opc_multidimarraynew, and opc_invokeinterface.
+ */
+
+ /**
+ * Create an instruction which requires no immediate operands
+ */
+ public static Insn create(int theOpCode) {
+ return new InsnSingle(theOpCode);
+ }
+
+ /**
+ * Create an instruction which requires a single constant from the
+ * constant pool as an immediate operand.
+ */
+ public static Insn create(int theOpCode, ConstBasic constValue) {
+ return new InsnConstOp(theOpCode, constValue);
+ }
+
+ /**
+ * Create an instruction which requires a single integral constant
+ * as an immediate operand.
+ */
+ public static Insn create(int theOpCode, int intValue) {
+ return new InsnIntOp(theOpCode, intValue);
+ }
+
+ /**
+ * Create an instruction which requires a single branch offset
+ * as an immediate operand.
+ */
+ public static Insn create(int theOpCode, InsnTarget target) {
+ return new InsnTargetOp(theOpCode, target);
+ }
+
+ /**
+ * Print the sequence of instructions to the output stream
+ */
+ public void printList(PrintStream out) {
+ Insn insn = this;
+ while (insn != null) {
+ insn.print(out, 0);
+ insn = insn.next();
+ }
+ }
+
+ /**
+ * Print this instruction to the output stream
+ */
+ public void printInsn(PrintStream out) {
+ print(out, 0);
+ }
+
+ /**
+ * Compares this instance with another for structural equality.
+ */
+ //@olsen: added method
+ public boolean isEqual(Stack msg, Object obj) {
+ if (!(obj instanceof Insn)) {
+ msg.push("obj/obj.getClass() = "
+ + (obj == null ? null : obj.getClass()));
+ msg.push("this.getClass() = "
+ + this.getClass());
+ return false;
+ }
+ Insn other = (Insn)obj;
+
+ if (this.insnOpcode != other.insnOpcode) {
+ // be tolerant against opc_ldc vs. opc_ldc_w
+ if (!((this.insnOpcode == opc_ldc
+ || this.insnOpcode == opc_ldc_w)
+ && (other.insnOpcode == opc_ldc
+ || other.insnOpcode == opc_ldc_w))) {
+ msg.push(String.valueOf("insnOpcode = "
+ + other.insnOpcode));
+ msg.push(String.valueOf("insnOpcode = "
+ + this.insnOpcode));
+ return false;
+ }
+ }
+ // offsets may differ due to different byte length
+ // (e.g. opc_ldc vs. opc_ldc_w)
+ //if (this.insnOffset != other.insnOffset) {
+ // msg.push(String.valueOf("insnOffset = "
+ // + other.insnOffset));
+ // msg.push(String.valueOf("insnOffset = "
+ // + this.insnOffset));
+ // return false;
+ //}
+ return true;
+ }
+
+ /**
+ * A printable representation
+ */
+ public String toString() {
+ return ("Insn: " + "insnOpcode(" + opName(insnOpcode) + ")"
+ + " insnOffset(" + insnOffset + ")");
+ }
+
+ /* package local methods */
+
+ abstract void print(PrintStream out, int indent);
+
+ abstract int store(byte[] buf, int index);
+
+ /* return the size of the instruction in bytes
+ * Note: some instructions are unable to answer correctly until their
+ * start offset is known
+ */
+ abstract int size();
+
+ /* Set the offset of the instruction and return the offset of the
+ following instruction */
+
+ final int resolveOffset(int pc) {
+ insnOffset = pc;
+ return pc + size();
+ }
+
+ Insn(int theOpcode, int theOffset) {
+ insnOpcode = theOpcode;
+ insnOffset = theOffset;
+ }
+
+ static int storeInt(byte buf[], int index, int v) {
+ buf[index++] = (byte) (v >> 24);
+ buf[index++] = (byte) ((v >> 16) & 0xff);
+ buf[index++] = (byte) ((v >> 8) & 0xff);
+ buf[index++] = (byte) (v & 0xff);
+ return index;
+ }
+
+
+ static int storeShort(byte buf[], int index, short v) {
+ buf[index++] = (byte) ((v >> 8) & 0xff);
+ buf[index++] = (byte) (v & 0xff);
+ return index;
+ }
+
+ static Insn read(InsnReadEnv insnEnv) {
+ boolean widen = false;
+ int pc = insnEnv.currentPC();
+
+ int op = insnEnv.getUByte();
+ if (op == opc_wide) {
+ widen = true;
+ op = insnEnv.getUByte();
+ }
+
+ switch (op) {
+ case opc_nop:
+ case opc_aconst_null:
+ case opc_iconst_m1:
+ case opc_iconst_0:
+ case opc_iconst_1:
+ case opc_iconst_2:
+ case opc_iconst_3:
+ case opc_iconst_4:
+ case opc_iconst_5:
+ case opc_lconst_0:
+ case opc_lconst_1:
+ case opc_fconst_0:
+ case opc_fconst_1:
+ case opc_fconst_2:
+ case opc_dconst_0:
+ case opc_dconst_1:
+ case opc_iload_0:
+ case opc_iload_1:
+ case opc_iload_2:
+ case opc_iload_3:
+ case opc_lload_0:
+ case opc_lload_1:
+ case opc_lload_2:
+ case opc_lload_3:
+ case opc_fload_0:
+ case opc_fload_1:
+ case opc_fload_2:
+ case opc_fload_3:
+ case opc_dload_0:
+ case opc_dload_1:
+ case opc_dload_2:
+ case opc_dload_3:
+ case opc_aload_0:
+ case opc_aload_1:
+ case opc_aload_2:
+ case opc_aload_3:
+ case opc_iaload:
+ case opc_laload:
+ case opc_faload:
+ case opc_daload:
+ case opc_aaload:
+ case opc_baload:
+ case opc_caload:
+ case opc_saload:
+ case opc_istore_0:
+ case opc_istore_1:
+ case opc_istore_2:
+ case opc_istore_3:
+ case opc_lstore_0:
+ case opc_lstore_1:
+ case opc_lstore_2:
+ case opc_lstore_3:
+ case opc_fstore_0:
+ case opc_fstore_1:
+ case opc_fstore_2:
+ case opc_fstore_3:
+ case opc_dstore_0:
+ case opc_dstore_1:
+ case opc_dstore_2:
+ case opc_dstore_3:
+ case opc_astore_0:
+ case opc_astore_1:
+ case opc_astore_2:
+ case opc_astore_3:
+ case opc_iastore:
+ case opc_lastore:
+ case opc_fastore:
+ case opc_dastore:
+ case opc_aastore:
+ case opc_bastore:
+ case opc_castore:
+ case opc_sastore:
+ case opc_pop:
+ case opc_pop2:
+ case opc_dup:
+ case opc_dup_x1:
+ case opc_dup_x2:
+ case opc_dup2:
+ case opc_dup2_x1:
+ case opc_dup2_x2:
+ case opc_swap:
+ case opc_iadd:
+ case opc_ladd:
+ case opc_fadd:
+ case opc_dadd:
+ case opc_isub:
+ case opc_lsub:
+ case opc_fsub:
+ case opc_dsub:
+ case opc_imul:
+ case opc_lmul:
+ case opc_fmul:
+ case opc_dmul:
+ case opc_idiv:
+ case opc_ldiv:
+ case opc_fdiv:
+ case opc_ddiv:
+ case opc_irem:
+ case opc_lrem:
+ case opc_frem:
+ case opc_drem:
+ case opc_ineg:
+ case opc_lneg:
+ case opc_fneg:
+ case opc_dneg:
+ case opc_ishl:
+ case opc_lshl:
+ case opc_ishr:
+ case opc_lshr:
+ case opc_iushr:
+ case opc_lushr:
+ case opc_iand:
+ case opc_land:
+ case opc_ior:
+ case opc_lor:
+ case opc_ixor:
+ case opc_lxor:
+ case opc_i2l:
+ case opc_i2f:
+ case opc_i2d:
+ case opc_l2i:
+ case opc_l2f:
+ case opc_l2d:
+ case opc_f2i:
+ case opc_f2l:
+ case opc_f2d:
+ case opc_d2i:
+ case opc_d2l:
+ case opc_d2f:
+ case opc_i2b:
+ case opc_i2c:
+ case opc_i2s:
+ case opc_lcmp:
+ case opc_fcmpl:
+ case opc_fcmpg:
+ case opc_dcmpl:
+ case opc_dcmpg:
+ case opc_ireturn:
+ case opc_lreturn:
+ case opc_freturn:
+ case opc_dreturn:
+ case opc_areturn:
+ case opc_return:
+ case opc_xxxunusedxxx:
+ case opc_arraylength:
+ case opc_athrow:
+ case opc_monitorenter:
+ case opc_monitorexit:
+ return new InsnSingle(op, pc);
+
+ case opc_ldc:
+ return new InsnConstOp(op, insnEnv.pool().constantAt(insnEnv.getUByte()),
+ pc);
+
+ case opc_ldc_w:
+ case opc_ldc2_w:
+ case opc_getstatic:
+ case opc_putstatic:
+ case opc_getfield:
+ case opc_putfield:
+ case opc_invokevirtual:
+ case opc_invokespecial:
+ case opc_invokestatic:
+ case opc_new:
+ case opc_anewarray:
+ case opc_checkcast:
+ case opc_instanceof:
+ return new InsnConstOp(op,
+ insnEnv.pool().constantAt(insnEnv.getUShort()),
+ pc);
+
+ case opc_iload:
+ case opc_lload:
+ case opc_fload:
+ case opc_dload:
+ case opc_aload:
+ case opc_istore:
+ case opc_lstore:
+ case opc_fstore:
+ case opc_dstore:
+ case opc_astore:
+ case opc_ret:
+ if (widen)
+ return new InsnIntOp(op, insnEnv.getShort(), pc);
+ else
+ return new InsnIntOp(op, insnEnv.getByte(), pc);
+
+ case opc_bipush: /* a byte constant */
+ case opc_newarray:
+ return new InsnIntOp(op, insnEnv.getByte(), pc);
+
+ case opc_sipush: /* a short constant */
+ return new InsnIntOp(op, insnEnv.getShort(), pc);
+
+ case opc_iinc:
+ if (widen)
+ return new InsnIInc(insnEnv.getUShort(), insnEnv.getShort(), pc);
+ else
+ return new InsnIInc(insnEnv.getUByte(), insnEnv.getByte(), pc);
+
+ case opc_ifeq:
+ case opc_ifne:
+ case opc_iflt:
+ case opc_ifge:
+ case opc_ifgt:
+ case opc_ifle:
+ case opc_if_icmpeq:
+ case opc_if_icmpne:
+ case opc_if_icmplt:
+ case opc_if_icmpge:
+ case opc_if_icmpgt:
+ case opc_if_icmple:
+ case opc_if_acmpeq:
+ case opc_if_acmpne:
+ case opc_goto:
+ case opc_jsr:
+ case opc_ifnull:
+ case opc_ifnonnull:
+ return new InsnTargetOp(op, insnEnv.getTarget(insnEnv.getShort()+pc), pc);
+
+ case opc_goto_w:
+ case opc_jsr_w:
+ return new InsnTargetOp(op, insnEnv.getTarget(insnEnv.getInt()+pc), pc);
+
+ case opc_tableswitch:
+ return InsnTableSwitch.read(insnEnv, pc);
+
+ case opc_lookupswitch:
+ return InsnLookupSwitch.read(insnEnv, pc);
+
+ case opc_invokeinterface:
+ return InsnInterfaceInvoke.read(insnEnv, pc);
+
+ case opc_multianewarray:
+ return InsnMultiDimArrayNew.read(insnEnv, pc);
+ }
+ throw new InsnError("Invalid byte code (" + op + ")");
+ }
+
+ /**
+ * Return the type of value manipulated by the load/store instruction
+ */
+ public static final int loadStoreDataType(int opcode) {
+ switch(opcode) {
+ case opc_iload:
+ case opc_iload_0:
+ case opc_iload_1:
+ case opc_iload_2:
+ case opc_iload_3:
+ case opc_istore:
+ case opc_istore_0:
+ case opc_istore_1:
+ case opc_istore_2:
+ case opc_istore_3:
+ case opc_iaload:
+ case opc_baload:
+ case opc_caload:
+ case opc_saload:
+ case opc_iastore:
+ case opc_bastore:
+ case opc_castore:
+ case opc_sastore:
+ return T_INT;
+
+ case opc_lload:
+ case opc_lload_0:
+ case opc_lload_1:
+ case opc_lload_2:
+ case opc_lload_3:
+ case opc_lstore:
+ case opc_lstore_0:
+ case opc_lstore_1:
+ case opc_lstore_2:
+ case opc_lstore_3:
+ case opc_laload:
+ case opc_lastore:
+ return T_LONG;
+
+ case opc_fload:
+ case opc_fload_0:
+ case opc_fload_1:
+ case opc_fload_2:
+ case opc_fload_3:
+ case opc_fstore:
+ case opc_fstore_0:
+ case opc_fstore_1:
+ case opc_fstore_2:
+ case opc_fstore_3:
+ case opc_faload:
+ case opc_fastore:
+ return T_FLOAT;
+
+ case opc_dload:
+ case opc_dload_0:
+ case opc_dload_1:
+ case opc_dload_2:
+ case opc_dload_3:
+ case opc_dstore:
+ case opc_dstore_0:
+ case opc_dstore_1:
+ case opc_dstore_2:
+ case opc_dstore_3:
+ case opc_daload:
+ case opc_dastore:
+ return T_DOUBLE;
+
+ case opc_aload:
+ case opc_aload_0:
+ case opc_aload_1:
+ case opc_aload_2:
+ case opc_aload_3:
+ case opc_astore:
+ case opc_astore_0:
+ case opc_astore_1:
+ case opc_astore_2:
+ case opc_astore_3:
+ case opc_aaload:
+ case opc_aastore:
+ return TC_OBJECT;
+
+ default:
+ throw new InsnError("not a load/store");
+ }
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/InsnConstOp.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/InsnConstOp.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/InsnConstOp.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/InsnConstOp.java Sun May 22 10:55:51 2005
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+
+import java.io.PrintStream;
+import java.util.Stack;
+
+/**
+ * An instruction which requires a single constant from the constant
+ * pool as an immediate operand
+ */
+public class InsnConstOp extends Insn {
+ /* The constant from the constant pool */
+ private ConstBasic constValue;
+
+ /* public accessors */
+
+ public int nStackArgs() {
+ int n = VMOp.ops[opcode()].nStackArgs();
+ if (n >= 0)
+ return n;
+ switch (opcode()) {
+ case opc_putstatic:
+ case opc_putfield:
+ {
+ ConstFieldRef fld = (ConstFieldRef) constValue;
+ String sig = fld.nameAndType().signature().asString();
+ if (sig.equals("J") || sig.equals("D"))
+ return (opcode() == opc_putfield) ? 3 : 2;
+ return (opcode() == opc_putfield) ? 2 : 1;
+ }
+ case opc_invokevirtual:
+ case opc_invokespecial:
+ case opc_invokestatic:
+ /* handle interface invoke too */
+ case opc_invokeinterface:
+ {
+ ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue;
+ String sig = meth.nameAndType().signature().asString();
+ int nMethodArgWords = Descriptor.countMethodArgWords(sig);
+ return nMethodArgWords +
+ ((opcode() == opc_invokestatic) ? 0 : 1);
+ }
+ default:
+ throw new InsnError("unexpected variable opcode");
+ }
+ }
+
+ public int nStackResults() {
+ int n = VMOp.ops[opcode()].nStackResults();
+ if (n >= 0)
+ return n;
+ switch (opcode()) {
+ case opc_getstatic:
+ case opc_getfield:
+ {
+ ConstFieldRef fld = (ConstFieldRef) constValue;
+ String sig = fld.nameAndType().signature().asString();
+ if (sig.equals("J") || sig.equals("D"))
+ return 2;
+ return 1;
+ }
+ case opc_invokevirtual:
+ case opc_invokespecial:
+ case opc_invokestatic:
+ /* handle interface invoke too */
+ case opc_invokeinterface:
+ {
+ ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue;
+ return Descriptor.countMethodReturnWords(
+ meth.nameAndType().signature().asString());
+ }
+ default:
+ throw new InsnError("unexpected variable opcode");
+ }
+ }
+
+ public String argTypes() {
+ switch (opcode()) {
+ case opc_putstatic:
+ case opc_putfield:
+ {
+ ConstFieldRef fld = (ConstFieldRef) constValue;
+ String sig = fld.nameAndType().signature().asString();
+ if (opcode() == opc_putstatic)
+ return sig;
+ else
+ return descriptorTypeOfObject(fld) + sig;
+ }
+ case opc_invokevirtual:
+ case opc_invokespecial:
+ case opc_invokestatic:
+ /* handle interface invoke too */
+ case opc_invokeinterface:
+ {
+ ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue;
+ String argSig =
+ Descriptor.extractArgSig(meth.nameAndType().signature().asString());
+ if (opcode() == opc_invokestatic)
+ return argSig;
+ else
+ return descriptorTypeOfObject(meth) + argSig;
+ }
+ default:
+ return VMOp.ops[opcode()].argTypes();
+ }
+ }
+
+ public String resultTypes() {
+ switch (opcode()) {
+ case opc_invokevirtual:
+ case opc_invokespecial:
+ case opc_invokestatic:
+ /* handle interface invoke too */
+ case opc_invokeinterface:
+ {
+ ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue;
+ String resultSig = Descriptor.extractResultSig(
+ meth.nameAndType().signature().asString());
+ if (resultSig.equals("V"))
+ return "";
+ return resultSig;
+ }
+ case opc_getstatic:
+ case opc_getfield:
+ {
+ ConstFieldRef fld = (ConstFieldRef) constValue;
+ return fld.nameAndType().signature().asString();
+ }
+ case opc_ldc:
+ case opc_ldc_w:
+ case opc_ldc2_w:
+ {
+ ConstValue constVal = (ConstValue) constValue;
+ return constVal.descriptor();
+ }
+ default:
+ return VMOp.ops[opcode()].resultTypes();
+ }
+ }
+
+ public boolean branches() {
+ /* invokes don't count as a branch */
+ return false;
+ }
+
+ /**
+ * Return the constant pool entry which is the immediate operand
+ */
+ public ConstBasic value() {
+ return constValue;
+ }
+
+ /**
+ * Modify the referenced constant
+ */
+ public void setValue(ConstBasic newValue) {
+ checkConstant(newValue);
+ constValue = newValue;
+ }
+
+ /**
+ * Compares this instance with another for structural equality.
+ */
+ //@olsen: added method
+ public boolean isEqual(Stack msg, Object obj) {
+ if (!(obj instanceof InsnConstOp)) {
+ msg.push("obj/obj.getClass() = "
+ + (obj == null ? null : obj.getClass()));
+ msg.push("this.getClass() = "
+ + this.getClass());
+ return false;
+ }
+ InsnConstOp other = (InsnConstOp)obj;
+
+ if (!super.isEqual(msg, other)) {
+ return false;
+ }
+
+ if (!this.constValue.isEqual(msg, other.constValue)) {
+ msg.push(String.valueOf("constValue = "
+ + other.constValue));
+ msg.push(String.valueOf("constValue = "
+ + this.constValue));
+ return false;
+ }
+ return true;
+ }
+
+ /* package local methods */
+
+ void print(PrintStream out, int indent) {
+ ClassPrint.spaces(out, indent);
+ out.println(offset() + " " + opName(opcode()) + " pool(" +
+ constValue.getIndex() + ")");
+ }
+
+ int store(byte[] buf, int index) {
+ if (opcode() == opc_ldc && !isNarrowldc())
+ buf[index++] = (byte) opc_ldc_w;
+ else
+ buf[index++] = (byte) opcode();
+ int constIndex = constValue.getIndex();
+ if (size() == 3)
+ buf[index++] = (byte) (constIndex >> 8);
+ buf[index++] = (byte)(constIndex & 0xff);
+ return index;
+ }
+
+ int size() {
+ return isNarrowldc() ? 2 : 3;
+ }
+
+ private boolean isNarrowldc() {
+ return (opcode() == opc_ldc && constValue.getIndex() < 256);
+ }
+
+
+ InsnConstOp(int theOpcode, ConstBasic theOperand) {
+ this(theOpcode, theOperand, NO_OFFSET);
+ }
+
+ InsnConstOp(int theOpcode, ConstBasic theOperand, int pc) {
+ super(theOpcode, pc);
+ constValue = theOperand;
+ checkConstant(theOperand);
+ if (theOpcode == opc_invokeinterface)
+ throw new InsnError("attempt to create an " + opName(theOpcode) +
+ " as an InsnConstOp instead of InsnInterfaceInvoke");
+ }
+
+ /* used only by InsnInterfaceInvoke, to make sure that opc_invokeinterface cannot
+ * come through the wrong path and miss its extra nArgsOp */
+ InsnConstOp(int theOpcode, ConstInterfaceMethodRef theOperand, int pc) {
+ super(theOpcode, pc);
+ constValue = theOperand;
+ checkConstant(theOperand);
+ }
+
+ private void checkConstant(ConstBasic operand) {
+ switch(opcode()) {
+ case opc_ldc:
+ case opc_ldc_w:
+ case opc_ldc2_w:
+ /* ConstValue */
+ if (operand == null ||
+ (! (operand instanceof ConstValue)))
+ throw new InsnError ("attempt to create an " + opName(opcode()) +
+ " without a ConstValue operand");
+ break;
+
+ case opc_getstatic:
+ case opc_putstatic:
+ case opc_getfield:
+ case opc_putfield:
+ /* ConstFieldRef */
+ if (operand == null ||
+ (! (operand instanceof ConstFieldRef)))
+ throw new InsnError ("attempt to create an " + opName(opcode()) +
+ " without a ConstFieldRef operand");
+ break;
+
+ case opc_invokevirtual:
+ case opc_invokespecial:
+ case opc_invokestatic:
+ /* ConstMethodRef */
+ if (operand == null ||
+ (! (operand instanceof ConstMethodRef)))
+ throw new InsnError ("attempt to create an " + opName(opcode()) +
+ " without a ConstMethodRef operand");
+ break;
+
+ case opc_invokeinterface:
+ /* ConstInterfaceMethodRef */
+ if (operand == null ||
+ (! (operand instanceof ConstInterfaceMethodRef)))
+ throw new InsnError("Attempt to create an " + opName(opcode()) +
+ " without a ConstInterfaceMethodRef operand");
+ break;
+
+ case opc_new:
+ case opc_anewarray:
+ case opc_checkcast:
+ case opc_instanceof:
+ /* ConstClass */
+ if (operand == null ||
+ (! (operand instanceof ConstClass)))
+ throw new InsnError ("attempt to create an " + opName(opcode()) +
+ " without a ConstClass operand");
+ break;
+
+ default:
+ throw new InsnError ("attempt to create an " + opName(opcode()) +
+ " with a constant operand");
+ }
+ }
+
+ private final String descriptorTypeOfObject(ConstBasicMemberRef memRef) {
+ String cname = memRef.className().className().asString();
+ return "L" + cname + ";";
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/InsnError.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/InsnError.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/InsnError.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/InsnError.java Sun May 22 10:55:51 2005
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.impl.enhancer.classfile;
+
+/**
+ * An exception thrown when an error occurs in encoding or decoding
+ * instruction sequences
+ */
+public class InsnError extends RuntimeException {
+ public InsnError(String s) {
+ super(s);
+ }
+}