Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/classfile/VMOp.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/classfile/VMOp.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/classfile/VMOp.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/classfile/VMOp.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,546 @@
+/*
+ * 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;
+
+/**
+ * Description of the VM opcodes
+ */
+public class VMOp implements VMConstants {
+ /* The opcode value */
+ private int opcodeValue;
+
+ /* The name of the opcode */
+ private String opcodeName;
+
+ /* The number of stack argument words */
+ private int stackArgs;
+
+ /* The number of stack result words */
+ private int stackResults;
+
+ /* The "type" signature of the stack argument words */
+ private String stackArgTypes;
+
+ /* The "type" signature of the stack result words */
+ private String stackResultTypes;
+
+ /* public accessors */
+
+ /**
+ * Return the opcode value
+ */
+ final public int opcode() {
+ return opcodeValue;
+ }
+
+ /**
+ * Return the opcode name
+ */
+ final public String name() {
+ return opcodeName;
+ }
+
+ /**
+ * Return the number of words of stack arguments expected by this operation.
+ * If the number is not a fixed value, return -1;
+ */
+ final public int nStackArgs() {
+ return stackArgs;
+ }
+
+ /**
+ * Return the number of words of stack results produced by this operation.
+ * If the number is not a fixed value, return -1;
+ */
+ final public int nStackResults() {
+ return stackResults;
+ }
+
+ /**
+ * Return the type descriptor for the stack arguments to the operation.
+ */
+ final public String argTypes() {
+ return stackArgTypes;
+ }
+
+ /**
+ * Return the type descriptor for the stack results of the operation.
+ */
+ final public String resultTypes() {
+ return stackResultTypes;
+ }
+
+ /**
+ * constructor for a VMOp
+ */
+
+ public VMOp(int theOpcode, String theOpcodeName, int nArgs, int nResults,
+ String argDescr, String resultDescr) {
+ opcodeValue = theOpcode;
+ opcodeName = theOpcodeName;
+ stackArgs = nArgs;
+ stackResults = nResults;
+ stackArgTypes = argDescr;
+ stackResultTypes = resultDescr;
+ }
+
+ /* package local methods */
+
+ static VMOp[] ops = {
+ /* | no change*/
+ new VMOp(opc_nop, "nop", 0, 0, "", ""),
+ /* | ... -> ..., null */
+ new VMOp(opc_aconst_null, "aconst_null", 0, 1, "", "A"),
+ /* | ... -> ..., -1 */
+ new VMOp(opc_iconst_m1, "iconst_m1", 0, 1, "", "I"),
+ /* | ... -> ..., 0 */
+ new VMOp(opc_iconst_0, "iconst_0", 0, 1, "", "I"),
+ /* | ... -> ..., 1 */
+ new VMOp(opc_iconst_1, "iconst_1", 0, 1, "", "I"),
+ /* | ... -> ..., 2 */
+ new VMOp(opc_iconst_2, "iconst_2", 0, 1, "", "I"),
+ /* | ... -> ..., 3 */
+ new VMOp(opc_iconst_3, "iconst_3", 0, 1, "", "I"),
+ /* | ... -> ..., 4 */
+ new VMOp(opc_iconst_4, "iconst_4", 0, 1, "", "I"),
+ /* | ... -> ..., 5 */
+ new VMOp(opc_iconst_5, "iconst_5", 0, 1, "", "I"),
+ /* | ... -> ..., 0<high/low>, 0<high/low> */
+ new VMOp(opc_lconst_0, "lconst_0", 0, 2, "", "J"),
+ /* | ... -> ..., 1<high/low>, 1<high/low> */
+ new VMOp(opc_lconst_1, "lconst_1", 0, 2, "", "J"),
+ /* | ... -> ..., 0.0f */
+ new VMOp(opc_fconst_0, "fconst_0", 0, 1, "", "F"),
+ /* | ... -> ..., 1.0f */
+ new VMOp(opc_fconst_1, "fconst_1", 0, 1, "", "F"),
+ /* | ... -> ..., 2.0f */
+ new VMOp(opc_fconst_2, "fconst_2", 0, 1, "", "F"),
+ /* | ... -> ..., 0.0<high/low>, 0.0<high/low> */
+ new VMOp(opc_dconst_0, "dconst_0", 0, 2, "", "D"),
+ /* | ... -> ..., 1.0<high/low>, 1.0<high/low> */
+ new VMOp(opc_dconst_1, "dconst_1", 0, 2, "", "D"),
+ /* byte1 | ... => ..., value */
+ new VMOp(opc_bipush, "bipush", 0, 1, "", "I"),
+ /* byte1 byte2 | ... => ..., value */
+ new VMOp(opc_sipush, "sipush", 0, 1, "", "I"),
+ /* indexbyte1 | ... => ..., item */
+ new VMOp(opc_ldc, "ldc", 0, 1, "", "W"),
+ /* indexbyte1 indexbyte2 | ... => ..., item */
+ new VMOp(opc_ldc_w, "ldc_w", 0, 1, "", "W"),
+ /* indexbyte1 indexbyte2 | ... => ..., item1, item2 */
+ new VMOp(opc_ldc2_w, "ldc2_w", 0, 2, "", "X"),
+ /* vindex | ... => ..., value<vindex> */
+ new VMOp(opc_iload, "iload", 0, 1, "", "I"),
+ /* vindex | ... => ..., value<vindex><h/l>, value<vindex><h/l> */
+ new VMOp(opc_lload, "lload", 0, 2, "", "J"),
+ /* vindex | ... => ..., value<vindex> */
+ new VMOp(opc_fload, "fload", 0, 1, "", "F"),
+ /* vindex | ... => ..., value<vindex><h/l>, value<vindex><h/l> */
+ new VMOp(opc_dload, "dload", 0, 2, "", "D"),
+ /* vindex | ... => ..., value<vindex> */
+ new VMOp(opc_aload, "aload", 0, 1, "", "A"),
+ /* | ... => ..., value<0> */
+ new VMOp(opc_iload_0, "iload_0", 0, 1, "", "I"),
+ /* | ... => ..., value<1> */
+ new VMOp(opc_iload_1, "iload_1", 0, 1, "", "I"),
+ /* | ... => ..., value<2> */
+ new VMOp(opc_iload_2, "iload_2", 0, 1, "", "I"),
+ /* | ... => ..., value<3> */
+ new VMOp(opc_iload_3, "iload_3", 0, 1, "", "I"),
+ /* | ... => ..., value<0><h/l>, value<0><h/l> */
+ new VMOp(opc_lload_0, "lload_0", 0, 2, "", "J"),
+ /* | ... => ..., value<1><h/l>, value<1><h/l> */
+ new VMOp(opc_lload_1, "lload_1", 0, 2, "", "J"),
+ /* | ... => ..., value<2><h/l>, value<2><h/l> */
+ new VMOp(opc_lload_2, "lload_2", 0, 2, "", "J"),
+ /* | ... => ..., value<3><h/l>, value<3><h/l> */
+ new VMOp(opc_lload_3, "lload_3", 0, 2, "", "J"),
+ /* | ... => ..., value<0> */
+ new VMOp(opc_fload_0, "fload_0", 0, 1, "", "F"),
+ /* | ... => ..., value<1> */
+ new VMOp(opc_fload_1, "fload_1", 0, 1, "", "F"),
+ /* | ... => ..., value<2> */
+ new VMOp(opc_fload_2, "fload_2", 0, 1, "", "F"),
+ /* | ... => ..., value<3> */
+ new VMOp(opc_fload_3, "fload_3", 0, 1, "", "F"),
+ /* | ... => ..., value<0><h/l>, value<0><h/l> */
+ new VMOp(opc_dload_0, "dload_0", 0, 2, "", "D"),
+ /* | ... => ..., value<1><h/l>, value<1><h/l> */
+ new VMOp(opc_dload_1, "dload_1", 0, 2, "", "D"),
+ /* | ... => ..., value<2><h/l>, value<2><h/l> */
+ new VMOp(opc_dload_2, "dload_2", 0, 2, "", "D"),
+ /* | ... => ..., value<3><h/l>, value<3><h/l> */
+ new VMOp(opc_dload_3, "dload_3", 0, 2, "", "D"),
+ /* | ... => ..., value<0> */
+ new VMOp(opc_aload_0, "aload_0", 0, 1, "", "A"),
+ /* | ... => ..., value<1> */
+ new VMOp(opc_aload_1, "aload_1", 0, 1, "", "A"),
+ /* | ... => ..., value<2> */
+ new VMOp(opc_aload_2, "aload_2", 0, 1, "", "A"),
+ /* | ... => ..., value<3> */
+ new VMOp(opc_aload_3, "aload_3", 0, 1, "", "A"),
+ /* | ..., arrayref, index => ..., value */
+ new VMOp(opc_iaload, "iaload", 2, 1, "AI", "I"),
+ /* | ..., arrayref, index => ..., value<h/l>, value<h/l> */
+ new VMOp(opc_laload, "laload", 2, 2, "AI", "J"),
+ /* | ..., arrayref, index => ..., value */
+ new VMOp(opc_faload, "faload", 2, 1, "AI", "F"),
+ /* | ..., arrayref, index => ..., value<h/l>, value<h/l> */
+ new VMOp(opc_daload, "daload", 2, 2, "AI", "D"),
+ /* | ..., arrayref, index => ..., value */
+ new VMOp(opc_aaload, "aaload", 2, 1, "AI", "A"),
+ /* | ..., arrayref, index => ..., value */
+ new VMOp(opc_baload, "baload", 2, 1, "AI", "I"),
+ /* | ..., arrayref, index => ..., value */
+ new VMOp(opc_caload, "caload", 2, 1, "AI", "I"),
+ /* | ..., arrayref, index => ..., value */
+ new VMOp(opc_saload, "saload", 2, 1, "AI", "I"),
+ /* vindex | ..., value => ... */
+ new VMOp(opc_istore, "istore", 1, 0, "I", ""),
+ /* vindex | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_lstore, "lstore", 2, 0, "J", ""),
+ /* vindex | ..., value => ... */
+ new VMOp(opc_fstore, "fstore", 1, 0, "F", ""),
+ /* vindex | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_dstore, "dstore", 2, 0, "D", ""),
+ /* vindex | ..., value => ... */
+ new VMOp(opc_astore, "astore", 1, 0, "A", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_istore_0, "istore_0", 1, 0, "I", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_istore_1, "istore_1", 1, 0, "I", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_istore_2, "istore_2", 1, 0, "I", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_istore_3, "istore_3", 1, 0, "I", ""),
+ /* | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_lstore_0, "lstore_0", 2, 0, "J", ""),
+ /* | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_lstore_1, "lstore_1", 2, 0, "J", ""),
+ /* | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_lstore_2, "lstore_2", 2, 0, "J", ""),
+ /* | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_lstore_3, "lstore_3", 2, 0, "J", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_fstore_0, "fstore_0", 1, 0, "F", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_fstore_1, "fstore_1", 1, 0, "F", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_fstore_2, "fstore_2", 1, 0, "F", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_fstore_3, "fstore_3", 1, 0, "F", ""),
+ /* | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_dstore_0, "dstore_0", 2, 0, "D", ""),
+ /* | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_dstore_1, "dstore_1", 2, 0, "D", ""),
+ /* | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_dstore_2, "dstore_2", 2, 0, "D", ""),
+ /* | ..., value<h/l>, value<h/l> => ... */
+ new VMOp(opc_dstore_3, "dstore_3", 2, 0, "D", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_astore_0, "astore_0", 1, 0, "A", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_astore_1, "astore_1", 1, 0, "A", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_astore_2, "astore_2", 1, 0, "A", ""),
+ /* | ..., value => ... */
+ new VMOp(opc_astore_3, "astore_3", 1, 0, "A", ""),
+ /* | ..., arrayref, index, value => ... */
+ new VMOp(opc_iastore, "iastore", 3, 0, "AII", ""),
+ /* | ..., arrayref, index, value<h/l>, value<h/l> => ... */
+ new VMOp(opc_lastore, "lastore", 4, 0, "AIJ", ""),
+ /* | ..., arrayref, index, value => ... */
+ new VMOp(opc_fastore, "fastore", 3, 0, "AIF", ""),
+ /* | ..., arrayref, index, value<h/l>, value<h/l> => ... */
+ new VMOp(opc_dastore, "dastore", 4, 0, "AID", ""),
+ /* | ..., arrayref, index, value => ... */
+ new VMOp(opc_aastore, "aastore", 3, 0, "AIA", ""),
+ /* | ..., arrayref, index, value => ... */
+ new VMOp(opc_bastore, "bastore", 3, 0, "AII", ""),
+ /* | ..., arrayref, index, value => ... */
+ new VMOp(opc_castore, "castore", 3, 0, "AII", ""),
+ /* | ..., arrayref, index, value => ... */
+ new VMOp(opc_sastore, "sastore", 3, 0, "AII", ""),
+ /* | ..., any => ... */
+ new VMOp(opc_pop, "pop", 1, 0, "W", ""),
+ /* | ..., any1, any2 => ... */
+ new VMOp(opc_pop2, "pop2", 2, 0, "WW", ""),
+ /* | ..., any => ..., any, any */
+ new VMOp(opc_dup, "dup", 1, 2, "W", "WW"),
+ /* | ..., any1, any2 => ..., any2, any1, any2 */
+ new VMOp(opc_dup_x1, "dup_x1", 2, 3, "WW", "WWW"),
+ /* | ..., any1, any2, any3 => ..., any3, any1, any2, any3 */
+ new VMOp(opc_dup_x2, "dup_x2", 3, 4, "WWW", "WWWW"),
+ /* | ..., any1, any2 => ..., any1, any2, any1, any2 */
+ new VMOp(opc_dup2, "dup2", 2, 4, "WW", "WWWW"),
+ /* | ..., any1, any2, any3 => ..., any2, any3, any1, any2, any3 */
+ new VMOp(opc_dup2_x1, "dup2_x1", 3, 5, "WWW", "WWWWW"),
+ /* | ..., any1, any2, any3, any4 => ..., any3, any4, any1, any2, any3, any4 */
+ new VMOp(opc_dup2_x2, "dup2_x2", 4, 6, "WWWW", "WWWWWW"),
+ /* | ..., any1, any2 => ..., any2, any1 */
+ new VMOp(opc_swap, "swap", 2, 2, "WW", "WW"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_iadd, "iadd", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_ladd, "ladd", 4, 2, "JJ", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_fadd, "fadd", 2, 1, "FF", "F"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_dadd, "dadd", 4, 2, "DD", "D"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_isub, "isub", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_lsub, "lsub", 4, 2, "JJ", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_fsub, "fsub", 2, 1, "FF", "F"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_dsub, "dsub", 4, 2, "DD", "D"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_imul, "imul", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_lmul, "lmul", 4, 2, "JJ", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_fmul, "fmul", 2, 1, "FF", "F"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_dmul, "dmul", 4, 2, "DD", "D"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_idiv, "idiv", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_ldiv, "ldiv", 4, 2, "JJ", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_fdiv, "fdiv", 2, 1, "FF", "F"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_ddiv, "ddiv", 4, 2, "DD", "D"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_irem, "irem", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_lrem, "lrem", 4, 2, "JJ", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_frem, "frem", 2, 1, "FF", "F"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_drem, "drem", 4, 2, "DD", "D"),
+ /* | ..., value => ..., result */
+ new VMOp(opc_ineg, "ineg", 1, 1, "I", "I"),
+ /* | ..., value<h/l>, value<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_lneg, "lneg", 2, 2, "J", "J"),
+ /* | ..., value => ..., result */
+ new VMOp(opc_fneg, "fneg", 1, 1, "F", "F"),
+ /* | ..., value<h/l>, value<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_dneg, "dneg", 2, 2, "D", "D"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_ishl, "ishl", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2 => ..., result */
+ new VMOp(opc_lshl, "lshl", 3, 2, "JI", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_ishr, "ishr", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2 => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_lshr, "lshr", 3, 2, "JI", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_iushr, "iushr", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2 => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_lushr, "lushr", 3, 2, "JI", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_iand, "iand", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_land, "land", 4, 2, "JJ", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_ior, "ior", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_lor, "lor", 4, 2, "JJ", "J"),
+ /* | ..., value1, value2 => ..., result */
+ new VMOp(opc_ixor, "ixor", 2, 1, "II", "I"),
+ /* | ..., value1<h/l>, value1<h/l>, value2<h/l>, value2<h/l> => ..., result<h/l>, result<h/l> */
+ new VMOp(opc_lxor, "lxor", 4, 2, "JJ", "J"),
+ /* vindex, const | no change */
+ new VMOp(opc_iinc, "iinc", 0, 0, "", ""),
+ /* | ..., value => ..., value<h/l>, value<h/l> */
+ new VMOp(opc_i2l, "i2l", 1, 2, "I", "J"),
+ /* | ..., value => ..., value */
+ new VMOp(opc_i2f, "i2f", 1, 1, "I", "F"),
+ /* | ..., value => ..., value<h/l>, value<h/l> */
+ new VMOp(opc_i2d, "i2d", 1, 2, "I", "D"),
+ /* | ..., value<h/l>, value<h/l> => ..., value */
+ new VMOp(opc_l2i, "l2i", 2, 1, "J", "I"),
+ /* | ..., value<h/l>, value<h/l> => ..., value */
+ new VMOp(opc_l2f, "l2f", 2, 1, "J", "F"),
+ /* | ..., value<h/l>, value<h/l> => ..., value<h/l>, value<h/l> */
+ new VMOp(opc_l2d, "l2d", 2, 2, "J", "D"),
+ /* | ..., value => ..., value */
+ new VMOp(opc_f2i, "f2i", 1, 1, "F", "I"),
+ /* | ..., value => ..., value<h/l>, value<h/l> */
+ new VMOp(opc_f2l, "f2l", 1, 2, "F", "J"),
+ /* | ..., value => ..., value<h/l>, value<h/l> */
+ new VMOp(opc_f2d, "f2d", 1, 2, "F", "D"),
+ /* | ..., value<h/l>, value<h/l> => ..., value */
+ new VMOp(opc_d2i, "d2i", 2, 1, "D", "I"),
+ /* | ..., value<h/l>, value<h/l> => ..., value<h/l>, value<h/l> */
+ new VMOp(opc_d2l, "d2l", 2, 2, "D", "J"),
+ /* | ..., value<h/l>, value<h/l> => ..., value */
+ new VMOp(opc_d2f, "d2f", 2, 1, "D", "F"),
+ /* | ..., value => ..., result */
+ new VMOp(opc_i2b, "i2b", 1, 1, "I", "I"),
+ /* | ..., value => ..., result */
+ new VMOp(opc_i2c, "i2c", 1, 1, "I", "I"),
+ /* | ..., value => ..., result */
+ new VMOp(opc_i2s, "i2s", 1, 1, "I", "I"),
+ /* | ..., v1<h/l>, v1<h/l>, v2<h/l>, v2<h/l> => ..., result */
+ new VMOp(opc_lcmp, "lcmp", 4, 1, "JJ", "I"),
+ /* | ..., v1<h/l>, v1<h/l>, v2<h/l>, v2<h/l> => ..., result */
+ new VMOp(opc_fcmpl, "fcmpl", 2, 1, "FF", "I"),
+ /* | ..., v1, v2 => ..., result */
+ new VMOp(opc_fcmpg, "fcmpg", 2, 1, "FF", "I"),
+ /* | ..., v1<h/l>, v1<h/l>, v2<h/l>, v2<h/l> => ..., result */
+ new VMOp(opc_dcmpl, "dcmpl", 4, 1, "DD", "I"),
+ /* | ..., v1<h/l>, v1<h/l>, v2<h/l>, v2<h/l> => ..., result */
+ new VMOp(opc_dcmpg, "dcmpg", 4, 1, "DD", "I"),
+ /* brbyte1, brbyte2 | ..., value => ... */
+ new VMOp(opc_ifeq, "ifeq", 1, 0, "I", ""),
+ /* brbyte1, brbyte2 | ..., value => ... */
+ new VMOp(opc_ifne, "ifne", 1, 0, "I", ""),
+ /* brbyte1, brbyte2 | ..., value => ... */
+ new VMOp(opc_iflt, "iflt", 1, 0, "I", ""),
+ /* brbyte1, brbyte2 | ..., value => ... */
+ new VMOp(opc_ifge, "ifge", 1, 0, "I", ""),
+ /* brbyte1, brbyte2 | ..., value => ... */
+ new VMOp(opc_ifgt, "ifgt", 1, 0, "I", ""),
+ /* brbyte1, brbyte2 | ..., value => ... */
+ new VMOp(opc_ifle, "ifle", 1, 0, "I", ""),
+ /* brbyte1, brbyte2 | ..., value1, value2 => ... */
+ new VMOp(opc_if_icmpeq, "if_icmpeq", 2, 0, "II", ""),
+ /* brbyte1, brbyte2 | ..., value1, value2 => ... */
+ new VMOp(opc_if_icmpne, "if_icmpne", 2, 0, "II", ""),
+ /* brbyte1, brbyte2 | ..., value1, value2 => ... */
+ new VMOp(opc_if_icmplt, "if_icmplt", 2, 0, "II", ""),
+ /* brbyte1, brbyte2 | ..., value1, value2 => ... */
+ new VMOp(opc_if_icmpge, "if_icmpge", 2, 0, "II", ""),
+ /* brbyte1, brbyte2 | ..., value1, value2 => ... */
+ new VMOp(opc_if_icmpgt, "if_icmpgt", 2, 0, "II", ""),
+ /* brbyte1, brbyte2 | ..., value1, value2 => ... */
+ new VMOp(opc_if_icmple, "if_icmple", 2, 0, "II", ""),
+ /* brbyte1, brbyte2 | ..., value1, value2 => ... */
+ new VMOp(opc_if_acmpeq, "if_acmpeq", 2, 0, "AA", ""),
+ /* brbyte1, brbyte2 | ..., value1, value2 => ... */
+ new VMOp(opc_if_acmpne, "if_acmpne", 2, 0, "AA", ""),
+ /* brbyte1, brbyte2 | no change */
+ new VMOp(opc_goto, "goto", 0, 0, "", ""),
+ /* brbyte1, brbyte2 | ... => ..., return_addr */
+ new VMOp(opc_jsr, "jsr", 0, 1, "", "W"),
+ /* vindex | no change */
+ new VMOp(opc_ret, "ret", 0, 0, "", ""),
+ /* ??? | ..., index => ... */
+ new VMOp(opc_tableswitch, "tableswitch", 1, 0, "I", ""),
+ /* ??? | ..., key => ... */
+ new VMOp(opc_lookupswitch, "lookupswitch", 1, 0, "I", ""),
+ /* | ..., value => [empty] */
+ new VMOp(opc_ireturn, "ireturn", 1, 0, "I", ""),
+ /* | ..., value<h/l>, value<h/l> => [empty] */
+ new VMOp(opc_lreturn, "lreturn", 2, 0, "J", ""),
+ /* | ..., value => [empty] */
+ new VMOp(opc_freturn, "freturn", 1, 0, "F", ""),
+ /* | ..., value<h/l>, value<h/l> => [empty] */
+ new VMOp(opc_dreturn, "dreturn", 2, 0, "D", ""),
+ /* | ..., value => [empty] */
+ new VMOp(opc_areturn, "areturn", 1, 0, "A", ""),
+ /* | ... => [empty] */
+ new VMOp(opc_return, "return", 0, 0, "", ""),
+ /* idxbyte1, idxbyte2 | ... => ..., value [ value2 ] */
+ new VMOp(opc_getstatic, "getstatic", 0, -1, "", "?"),
+ /* idxbyte1, idxbyte2 | ..., value [ value2 ] => ... */
+ new VMOp(opc_putstatic, "putstatic", -1, 0, "?", ""),
+ /* idxbyte1, idxbyte2 | ..., objectref => ..., value [ value2 ] */
+ new VMOp(opc_getfield, "getfield", 1, -1, "A", "?"),
+ /* idxbyte1, idxbyte2 | ..., objectref, value [ value2 ] => ... */
+ new VMOp(opc_putfield, "putfield", -1, 0, "A?", ""),
+ /* idxbyte1, idxbyte2 | ..., objectref, [args] => ... */
+ new VMOp(opc_invokevirtual, "invokevirtual", -1, -1, "A?", "?"),
+ /* idxbyte1, idxbyte2 | ..., objectref, [args] => ... */
+ new VMOp(opc_invokespecial, "invokespecial", -1, -1, "A?", "?"),
+ /* idxbyte1, idxbyte2 | ..., [args] => ... */
+ new VMOp(opc_invokestatic, "invokestatic", -1, -1, "?", "?"),
+ /* idxbyte1, idxbyte2, nargs, rsvd | ..., objectref, [args] => ... */
+ new VMOp(opc_invokeinterface, "invokeinterface", -1, -1, "A?", "?"),
+ /* */
+ new VMOp(opc_xxxunusedxxx, "xxxunusedxxx", 0, 0, "", ""),
+ /* idxbyte1, idxbyte2 | ... => ..., objectref */
+ new VMOp(opc_new, "new", 0, 1, "", "A"),
+ /* atype | ..., size => ..., result */
+ new VMOp(opc_newarray, "newarray", 1, 1, "I", "A"),
+ /* indexbyte1, indexbyte2 | ..., size => ..., result */
+ new VMOp(opc_anewarray, "anewarray", 1, 1, "I", "A"),
+ /* | ..., objectref => ..., length */
+ new VMOp(opc_arraylength, "arraylength", 1, 1, "A", "I"),
+ /* | ..., objectref => [undefined] */
+ new VMOp(opc_athrow, "athrow", 1, 0, "A", "?"),
+ /* idxbyte1, idxbyte2 | ..., objectref => ..., objectref */
+ new VMOp(opc_checkcast, "checkcast", 1, 1, "A", "A"),
+ /* idxbyte1, idxbyte2 | ..., objectref => ..., result */
+ new VMOp(opc_instanceof, "instanceof", 1, 1, "A", "I"),
+ /* | ..., objectref => ... */
+ new VMOp(opc_monitorenter, "monitorenter", 1, 0, "A", ""),
+ /* | ..., objectref => ... */
+ new VMOp(opc_monitorexit, "monitorexit", 1, 0, "A", ""),
+ /* an instruction | special */
+ new VMOp(opc_wide, "wide", 0, 0, "", ""),
+ /* indexbyte1, indexbyte2, dimensions | ..., size1, ..., sizen => ..., result*/
+ new VMOp(opc_multianewarray, "multianewarray", -1, 1, "?", "A"),
+ /* brbyte1, brbyte2 | ..., value => ... */
+ new VMOp(opc_ifnull, "ifnull", 1, 0, "A", ""),
+ /* brbyte1, brbyte2 | ..., value => ... */
+ new VMOp(opc_ifnonnull, "ifnonnull", 1, 0, "A", ""),
+ /* brbyte1, brbyte2, brbyte3, brbyte4 | no change */
+ new VMOp(opc_goto_w, "goto_w", 0, 0, "", ""),
+ /* brbyte1, brbyte2, brbyte3, brbyte4 | ... => ..., return_addr */
+ new VMOp(opc_jsr_w, "jsr_w", 0, 1, "", "W") };
+
+ /**
+ * Check that each entry in the ops array has a valid VMOp entry
+ */
+ private static void check() {
+ for (int i=0; i<=opc_jsr_w; i++) {
+ VMOp op = ops[i];
+ if (op == null)
+ throw new InsnError ("null VMOp for " + i);
+ if (op.opcode() != i)
+ throw new InsnError ("bad opcode for " + i);
+
+ if (1 == 0) {
+ /* check arg/result data */
+ checkTypes(op.argTypes(), op.nStackArgs(), op);
+ checkTypes(op.resultTypes(), op.nStackResults(), op);
+ }
+ }
+ }
+
+ private static void checkTypes(String types, int n, VMOp op) {
+ for (int i=0; i<types.length(); i++) {
+ char c = types.charAt(i);
+ if (c == '?')
+ return;
+ if (c == 'J' || c == 'X' || c == 'D')
+ n -= 2;
+ else
+ n -= 1;
+ }
+ if (n != 0)
+ throw new InsnError ("Bad arg/result for VMOp " + op.opcodeName);
+ }
+
+ static {
+ check();
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/core/Analyzer.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/core/Analyzer.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/core/Analyzer.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/core/Analyzer.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,1586 @@
+/*
+ * 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.core;
+
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.HashMap;
+
+import org.apache.jdo.impl.enhancer.classfile.ClassAttribute;
+import org.apache.jdo.impl.enhancer.classfile.ClassField;
+import org.apache.jdo.impl.enhancer.classfile.ClassFile;
+import org.apache.jdo.impl.enhancer.classfile.ClassMethod;
+import org.apache.jdo.impl.enhancer.classfile.ConstClass;
+import org.apache.jdo.impl.enhancer.classfile.ConstantPool;
+import org.apache.jdo.impl.enhancer.classfile.GenericAttribute;
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaData;
+import org.apache.jdo.impl.enhancer.util.Support;
+
+
+
+
+
+/**
+ * Analyzes a class for enhancement.
+ */
+final class Analyzer
+ extends Support
+ implements JDOConstants, EnhancerConstants
+{
+ /**
+ * The class is not to be modified by the enahncer.
+ */
+ static public final int CC_Unenhancable = -2;
+
+ /**
+ * The class is detected to be enhanced already and is not to be modifed.
+ */
+ static public final int CC_PreviouslyEnhanced = -1;
+
+ /**
+ * The enhancement status of the class hasn't been determined yet.
+ */
+ static public final int CC_PersistenceUnknown = 0;
+
+ /**
+ * The class is to be enhanced for persistence-awareness.
+ */
+ static public final int CC_PersistenceAware = 1;
+
+ /**
+ * The class is to be enhanced for specific persistence-capability
+ * (class does extend another persistence-capable class).
+ */
+ static public final int CC_PersistenceCapable = 2;
+
+ /**
+ * The class is to be enhanced for generic and specific
+ * persistence-capability (class does not extend another
+ * persistence-capable class).
+ */
+ static public final int CC_PersistenceCapableRoot = 3;
+
+ /**
+ * The names of the jdo fields of persistene-capable classes.
+ */
+ static private final Set jdoFieldNames = new HashSet();
+ static
+ {
+ jdoFieldNames.add(JDO_PC_jdoStateManager_Name);
+ jdoFieldNames.add(JDO_PC_jdoFlags_Name);
+ jdoFieldNames.add(JDO_PC_jdoInheritedFieldCount_Name);
+ jdoFieldNames.add(JDO_PC_jdoFieldNames_Name);
+ jdoFieldNames.add(JDO_PC_jdoFieldTypes_Name);
+ jdoFieldNames.add(JDO_PC_jdoFieldFlags_Name);
+ jdoFieldNames.add(JDO_PC_jdoPersistenceCapableSuperclass_Name);
+ }
+
+ /**
+ * The classfile's enhancement controller.
+ */
+ private final Controller control;
+
+ /**
+ * The classfile to be enhanced.
+ */
+ private final ClassFile classFile;
+
+ /**
+ * The class name in VM form.
+ */
+ private final String className;
+
+ /**
+ * The class name in user ('.' delimited) form.
+ */
+ private final String userClassName;
+
+ /**
+ * The classfile's constant pool.
+ */
+ private final ConstantPool pool;
+
+ /**
+ * Repository for the enhancement options.
+ */
+ private final Environment env;
+
+ /**
+ * Repository for JDO meta-data on classes.
+ */
+ private final EnhancerMetaData meta;
+
+ /**
+ * What type of class is this with respect to persistence.
+ */
+ private int persistenceType = CC_PersistenceUnknown;
+
+ /**
+ * The name of the persistence-capable superclass if defined.
+ */
+ private String pcSuperClassName;
+
+ /**
+ * The name of the persistence-capable rootclass if defined.
+ */
+ private String pcRootClassName;
+
+ /**
+ * The name of this class or the next persistence-capable superclass
+ * that owns a key class, or the PC rootclass if none defines a key class.
+ */
+ private String pcKeyOwnerClassName;
+
+ /**
+ * The name next persistence-capable superclass that owns a key class,
+ * or the PC rootclass if none defines a key class.
+ */
+ private String pcSuperKeyOwnerClassName;
+
+ /**
+ * The name of the key class if defined.
+ */
+ private String keyClassName;
+
+ /**
+ * The name of the key class of the next persistence-capable superclass
+ * that defines one.
+ */
+ private String superKeyClassName;
+
+ /**
+ * The number of key fields.
+ */
+ private int keyFieldCount;
+
+ /**
+ * The indexes of all key fields.
+ */
+ private int[] keyFieldIndexes;
+
+ /**
+ * The number of managed fields.
+ */
+ private int managedFieldCount;
+
+ /**
+ * The number of annotated fields.
+ */
+ private int annotatedFieldCount;
+
+ /**
+ * The names of all annotated fields sorted by relative field index.
+ */
+ private String[] annotatedFieldNames;
+
+ /**
+ * The type names of all annotated fields sorted by relative field index.
+ */
+ private String[] annotatedFieldSigs;
+
+ /**
+ * The java access modifiers of all annotated fields sorted by relative
+ * field index.
+ */
+ private int[] annotatedFieldMods;
+
+ /**
+ * The jdo flags of all annotated fields sorted by relative field index.
+ */
+ private int[] annotatedFieldFlags;
+
+ /**
+ * The map of found JDO fields.
+ */
+ private final Map jdoLikeFields = new HashMap(20);
+
+ /**
+ * The map of found JDO methods
+ */
+ private final Map jdoLikeMethods = new HashMap(50);
+
+ /**
+ * The map of found JDO methods
+ */
+ private final Map annotatableMethods = new HashMap(100);
+
+ /**
+ * True if a jdo member has been seen in this class.
+ */
+ private boolean hasImplementsPC = false;
+ private boolean hasGenericJDOFields = false;
+ private boolean hasGenericJDOMethods = false;
+ private boolean hasGenericJDOMembers = false;
+ private boolean hasSpecificJDOFields = false;
+ private boolean hasSpecificJDOMethods = false;
+ private boolean hasSpecificJDOMembers = false;
+ private boolean hasCallbackJDOMethods = false;
+ private boolean hasJDOMembers = false;
+
+ /**
+ * True if the class has a default (no-argument) constructor.
+ */
+ private boolean hasDefaultConstructor = false;
+
+ //^olsen: performance opt.: make these fields of type ClassMethod
+
+ /**
+ * True if the class has a static initializer block.
+ */
+ private boolean hasStaticInitializer = false;
+
+ /**
+ * True if the class has a clone() method.
+ */
+ private boolean hasCloneMethod = false;
+
+ /**
+ * True if the class has a writeObject(java.io.ObjectOutputStream) method.
+ */
+ private boolean hasWriteObjectMethod = false;
+
+ /**
+ * True if the class has a writeReplace() method.
+ */
+ private boolean hasWriteReplaceMethod = false;
+
+ /**
+ * True if the class has a readObject(java.io.ObjectInputStream) method.
+ */
+ private boolean hasReadObjectMethod = false;
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Constructor
+ */
+ public Analyzer(Controller control,
+ Environment env)
+ {
+ affirm(control != null);
+ affirm(env != null);
+
+ this.control = control;
+ this.classFile = control.getClassFile();
+ this.className = classFile.classNameString();
+ this.userClassName = classFile.userClassName();
+ this.pool = classFile.pool();
+ this.env = env;
+ this.meta = env.getEnhancerMetaData();
+
+ affirm(classFile != null);
+ affirm(className != null);
+ affirm(userClassName != null);
+ affirm(pool != null);
+ affirm(meta != null);
+ }
+
+ /**
+ * Returns the class file which we are operating on.
+ */
+ public ClassFile getClassFile()
+ {
+ return classFile;
+ }
+
+ /**
+ * Return the persistence type for this class
+ */
+ public int getPersistenceType()
+ {
+ return persistenceType;
+ }
+
+ /**
+ * Returns true if the class has been analyzed already.
+ */
+ public boolean isAnalyzed()
+ {
+ return (persistenceType != CC_PersistenceUnknown);
+ }
+
+ /**
+ * Returns true if the class is one which should be a candidate for
+ * annotation.
+ */
+ public boolean isAnnotateable()
+ {
+ return (persistenceType >= CC_PersistenceUnknown);
+ }
+
+ /**
+ * Returns true if the class is to be enhanced for persistence-capability.
+ */
+ public boolean isAugmentable()
+ {
+ return (persistenceType >= CC_PersistenceCapable);
+ }
+
+ /**
+ * Returns true if the class is to be enhanced as least-derived,
+ * persistence-capable class.
+ */
+ public boolean isAugmentableAsRoot()
+ {
+ return (persistenceType >= CC_PersistenceCapableRoot);
+ }
+
+ /**
+ * Returns the methods that are candidates for annotation.
+ */
+ public Collection getAnnotatableMethods()
+ {
+ return annotatableMethods.values();
+ }
+
+ /**
+ * Returns the name of the persistence-capable superclass if defined.
+ */
+ public String getPCSuperClassName()
+ {
+ return pcSuperClassName;
+ }
+
+ /**
+ * Returns the name of the persistence-capable rootclass if defined.
+ */
+ public String getPCRootClassName()
+ {
+ return pcRootClassName;
+ }
+
+ /**
+ * Returns the name of this class or the next persistence-capable
+ * superclass that owns a key class.
+ */
+ public String getPCKeyOwnerClassName()
+ {
+ return pcKeyOwnerClassName;
+ }
+
+ /**
+ * Returns the name of this class or the next persistence-capable
+ * that owns a key class.
+ */
+ public String getPCSuperKeyOwnerClassName()
+ {
+ return pcSuperKeyOwnerClassName;
+ }
+
+ /**
+ * Returns the name of the key class if defined.
+ */
+ public String getKeyClassName()
+ {
+ return keyClassName;
+ }
+
+ /**
+ * Returns the name of the key class of the next persistence-capable
+ * superclass that defines one.
+ */
+ public String getSuperKeyClassName()
+ {
+ return superKeyClassName;
+ }
+
+ /**
+ * Returns the number of key field.
+ */
+ public int getKeyFieldCount()
+ {
+ return keyFieldCount;
+ }
+
+ /**
+ * Returns the names of the key fields.
+ */
+ public int[] getKeyFieldIndexes()
+ {
+ return keyFieldIndexes;
+ }
+
+ /**
+ * Returns the number of managed field.
+ */
+ public int getManagedFieldCount()
+ {
+ return managedFieldCount;
+ }
+
+ /**
+ * Returns the number of annotated field.
+ */
+ public int getAnnotatedFieldCount()
+ {
+ return annotatedFieldCount;
+ }
+
+ /**
+ * Returns the names of the annotated fields.
+ */
+ public String[] getAnnotatedFieldNames()
+ {
+ return annotatedFieldNames;
+ }
+
+ /**
+ * Returns the types names of the annotated fields.
+ */
+ public String[] getAnnotatedFieldSigs()
+ {
+ return annotatedFieldSigs;
+ }
+
+ /**
+ * Returns the Java access modifiers of the annotated fields.
+ */
+ public int[] getAnnotatedFieldMods()
+ {
+ return annotatedFieldMods;
+ }
+
+ /**
+ * Returns the JDO flags of the annotated fields.
+ */
+ public int[] getAnnotatedFieldFlags()
+ {
+ return annotatedFieldFlags;
+ }
+
+ /**
+ * Returns true if the class has a default (no-argument) constructor.
+ */
+ public boolean hasDefaultConstructor()
+ {
+ return hasDefaultConstructor;
+ }
+
+ /**
+ * Returns true if the class has a static initializer block.
+ */
+ public boolean hasStaticInitializer()
+ {
+ return hasStaticInitializer;
+ }
+
+ /**
+ * Returns true if the class has a clone() method.
+ */
+ public boolean hasCloneMethod()
+ {
+ return hasCloneMethod;
+ }
+
+ /**
+ * Returns true if the class has a writeObject() method.
+ */
+ public boolean hasWriteObjectMethod()
+ {
+ return hasWriteObjectMethod;
+ }
+
+ /**
+ * Returns true if the class has a writeReplace() method.
+ */
+ public boolean hasWriteReplaceMethod()
+ {
+ return hasWriteReplaceMethod;
+ }
+
+ /**
+ * Returns true if the class has a readObject() method.
+ */
+ public boolean hasReadObjectMethod()
+ {
+ return hasReadObjectMethod;
+ }
+
+ /**
+ * Returns true if the class already provides the JDO augmentation.
+ */
+ public boolean hasJDOAugmentation()
+ {
+ return hasJDOMembers;
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Analyzes the class for existing augmentation.
+ */
+ public void scan()
+ {
+ env.message("scanning class " + userClassName);
+
+ // skip previously enhanced files
+ checkForEnhancedAttribute();
+ if (!isAnnotateable()) {
+ return;
+ }
+
+ // skip unenhancable files
+ initPersistenceType();
+ if (!isAnnotateable()) {
+ return;
+ }
+ affirm(persistenceType > CC_Unenhancable);
+
+ scanFields();
+ scanMethods();
+
+ if (isAugmentable()) {
+ checkPCFeasibility();
+ checkSpecificAugmentation();
+ checkCallbackAugmentation();
+
+ if (isAugmentableAsRoot()) {
+ checkGenericAugmentation();
+ }
+ }
+
+ //^olsen: check
+/*
+ //@olsen: check whether member starts with the reserved jdo prefix
+ if (methodName.startsWith("jdo")) {
+ //@olsen: issue a warning only
+ env.warning(
+ getI18N("enhancer.class_has_jdo_like_member",
+ userClassName, methodName));
+ return;
+ }
+ //@olsen: check whether member starts with the reserved jdo prefix
+ if (fieldName.startsWith("jdo")) {
+ //@olsen: issue a warning only
+ env.warning(
+ getI18N("enhancer.class_has_jdo_like_member",
+ userClassName, fieldName));
+ return;
+ }
+*/
+ }
+
+ /**
+ * Scans the attributes of a ClassFile
+ */
+ private void checkForEnhancedAttribute()
+ {
+ for (Enumeration e = classFile.attributes().elements();
+ e.hasMoreElements();) {
+ final ClassAttribute attr = (ClassAttribute)e.nextElement();
+ final String attrName = attr.attrName().asString();
+ if (SUNJDO_PC_EnhancedAttribute.equals(attrName)) {
+ persistenceType = CC_PreviouslyEnhanced;
+
+ // At some point we may want to consider stripping old
+ // annotations and re-annotating, but not yet
+ env.message("ignoring previously enhanced class "
+ + userClassName);
+ return;
+ }
+ }
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Sets the persistence type of a class according to JDO metadata.
+ */
+ private void initPersistenceType()
+ {
+ affirm(persistenceType == CC_PersistenceUnknown);
+
+ // check if class is known not to be changed
+ final EnhancerMetaData meta = env.getEnhancerMetaData();
+ if (meta.isKnownUnenhancableClass(className)) {
+ persistenceType = CC_Unenhancable;
+ return;
+ }
+
+ // check if class is persistence-capable
+ if (meta.isPersistenceCapableClass(className)) {
+ pcSuperClassName
+ = meta.getPersistenceCapableSuperClass(className);
+ pcRootClassName
+ = meta.getPersistenceCapableRootClass(className);
+ affirm(pcSuperClassName == null || pcRootClassName != null);
+
+ persistenceType
+ = (pcSuperClassName == null
+ ? CC_PersistenceCapableRoot
+ : CC_PersistenceCapable);
+
+ //^olsen: assert consistency between Java and JDO metadata
+ affirm(!classFile.isInterface());
+ //affirm(!classFile.isInnerClass());
+
+ //^olsen: assert consistency between Java and JDO metadata
+ // disallow enhancing classes not derived from java.lang.Object
+ final ConstClass superConstClass = classFile.superName();
+ affirm(superConstClass != null);
+
+ // non-pc-root classes must not derive from java.lang.Object
+ affirm(pcSuperClassName == null
+ || !superConstClass.asString().equals("java/lang/Object"));
+
+ // define the PC key owner class
+ pcKeyOwnerClassName = className;
+ while (meta.getKeyClass(pcKeyOwnerClassName) == null) {
+ final String pcSuperClassName
+ = meta.getPersistenceCapableSuperClass(
+ pcKeyOwnerClassName);
+ if (pcSuperClassName == null)
+ break;
+ pcKeyOwnerClassName = pcSuperClassName;
+ }
+ affirm(pcKeyOwnerClassName != null);
+
+ // define the PC super key owner class
+ pcSuperKeyOwnerClassName = pcSuperClassName;
+ if (pcSuperKeyOwnerClassName != null) {
+ while (meta.getKeyClass(pcSuperKeyOwnerClassName) == null) {
+ final String pcSuperClassName
+ = meta.getPersistenceCapableSuperClass(
+ pcSuperKeyOwnerClassName);
+ if (pcSuperClassName == null)
+ break;
+ pcSuperKeyOwnerClassName = pcSuperClassName;
+ }
+ affirm(pcKeyOwnerClassName != null);
+ }
+
+ keyClassName
+ = meta.getKeyClass(className);
+ superKeyClassName
+ = meta.getSuperKeyClass(className);
+ affirm(superKeyClassName == null || pcSuperClassName != null);
+ }
+ }
+
+ /**
+ * Scans the fields.
+ */
+ private void scanFields()
+ {
+ // all fields for which accessor/mutator needs to be generated
+ final Map annotatedFieldMap = new HashMap();
+
+ if (isAugmentable()) {
+ // loop over class fields to declare them to the model
+ for (final Enumeration e = classFile.fields().elements();
+ e.hasMoreElements();) {
+ final ClassField field = (ClassField)e.nextElement();
+ final String name = field.name().asString();
+ final String sig = field.signature().asString();
+
+ // skip jdo fields
+ if (jdoFieldNames.contains(name)) {
+ continue;
+ }
+
+ // skip static fields
+ if (field.isStatic()) {
+ continue;
+ }
+
+ // skip known non-managed fields
+ if (meta.isKnownNonManagedField(className, name, sig)) {
+ continue;
+ }
+
+ // remember field requiring accessor/mutator
+ Object obj = annotatedFieldMap.put(name, field);
+ affirm(obj == null,
+ ("Error in classfile: repeated declaration of field: "
+ + userClassName + "." + name));
+
+ // skip final, transient fields
+ if (field.isFinal()
+ || field.isTransient()) {
+ continue;
+ }
+
+ if (false) {
+ System.out.println("Analyzer.scanFields(): declaring "
+ + className + "." + name + " : " + sig);
+ }
+ meta.declareField(className, name, sig);
+ }
+ }
+
+ // nr of fields needing accessor/mutator methods
+ annotatedFieldCount = annotatedFieldMap.size();
+
+ // get managed field names from meta data
+ final String[] managedFieldNames = meta.getManagedFields(className);
+ affirm(managedFieldNames != null);
+ managedFieldCount = managedFieldNames.length;
+ final Set managedFieldNamesSet
+ = new HashSet(Arrays.asList(managedFieldNames));
+ affirm(managedFieldNamesSet.size() == managedFieldCount,
+ "JDO metadata: returned duplicate managed fields.");
+ affirm(managedFieldCount <= annotatedFieldCount,
+ "JDO metadata: managed fields exceed annotated fields.");
+
+ // data structures for key fields
+ final String[] keyFieldNames = meta.getKeyFields(className);
+ affirm(keyFieldNames != null);
+ keyFieldCount = keyFieldNames.length;
+ affirm(keyFieldCount == 0 || keyClassName != null,
+ "JDO metadata: returned key fields but no key class.");
+ final Set keyFieldNamesSet
+ = new HashSet(Arrays.asList(keyFieldNames));
+ affirm(keyFieldNamesSet.size() == keyFieldCount,
+ "JDO metadata: returned duplicate key fields.");
+ affirm(keyFieldCount <= managedFieldCount,
+ "JDO metadata: key fields exceed managed fields.");
+
+ // loop over class fields to compute 'jdo*' and key/managed fields
+ for (final Enumeration e = classFile.fields().elements();
+ e.hasMoreElements();) {
+ final ClassField field = (ClassField)e.nextElement();
+ final String name = field.name().asString();
+ final String sig = field.signature().asString();
+ final String userFieldName = userClassName + "." + name;
+
+ if (false) {
+ System.out.println("Analyzer.scanFields(): scanning "
+ + className + "." + name + " : " + sig);
+ }
+
+ // map 'jdo*' field names to class fields
+ if (name.startsWith("jdo")) {
+ final Object f = jdoLikeFields.put(name, field);
+ affirm(f == null);
+ }
+
+ // skip non-managed fields
+ if (!managedFieldNamesSet.contains(name)) {
+ affirm(!meta.isManagedField(className, name));
+
+ // check for non-managed key field
+ affirm(!keyFieldNamesSet.contains(name),
+ ("JDO metadata: reported the field " + userFieldName
+ + " to be non-managed but key."));
+ continue;
+ }
+ affirm(meta.isManagedField(className, name));
+
+ // check for managed static field
+ affirm(!field.isStatic(),
+ ("JDO metadata: reported the field " + userFieldName
+ + " to be managed though it's static."));
+
+ // check for managed final field
+ affirm(!field.isFinal(),
+ ("JDO metadata: reported the field " + userFieldName
+ + " to be managed though it's final."));
+
+ // allow for managed transient fields
+
+//^olsen: adopt
+/*
+ r[i++] = hasField(
+ out,
+ Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC,
+ long.class,
+ "serialVersionUID");
+*/
+ }
+
+ // get the managed field flags ordered by relative index
+ final int[] managedFieldFlags
+ = meta.getFieldFlags(className, managedFieldNames);
+
+ // compute the managed field types ordered by relative index
+ // and key field indexes
+ int j = 0;
+ keyFieldIndexes = new int[keyFieldCount];
+ final String[] managedFieldSigs = new String[managedFieldCount];
+ final int[] managedFieldMods = new int[managedFieldCount];
+ for (int i = 0; i < managedFieldCount; i++) {
+ final String name = managedFieldNames[i];
+ affirm(name != null);
+
+ // assert consistency between Java and JDO metadata
+ final ClassField field = (ClassField)annotatedFieldMap.get(name);
+ affirm(field != null,
+ ("The managed field " + userClassName + "." + name +
+ " is not declared by the class."));
+ affirm(!field.isStatic(),
+ ("The managed field " + userClassName + "." + name +
+ " is static."));
+ affirm(!field.isFinal(),
+ ("The managed field " + userClassName + "." + name +
+ " is final."));
+
+ // mark managed field as taken care of
+ annotatedFieldMap.remove(name);
+
+ // assign key field index
+ if (keyFieldNamesSet.contains(name)) {
+ affirm(meta.isKeyField(className, name));
+ keyFieldIndexes[j++] = i;
+ }
+
+ // add field type and Java access modifers
+ managedFieldSigs[i] = field.signature().asString();
+ managedFieldMods[i] = field.access();
+
+ // set the serializable bit if field is not (Java) transient
+ // This code might be removed as soon as the metadata is able
+ // to retrieve the info as part of meta.getFieldFlags.
+ if (!field.isTransient()) {
+ managedFieldFlags[i] |= EnhancerMetaData.SERIALIZABLE;
+ }
+
+ if (false) {
+ System.out.println("managed field: "
+ + className + "." + name + " : {");
+ System.out.println(" sigs = " + managedFieldSigs[i]);
+ System.out.println(" mods = "
+ + Integer.toHexString(managedFieldMods[i]));
+ System.out.println(" flags = "
+ + Integer.toHexString(managedFieldFlags[i]));
+ }
+ }
+
+ // post conditions of managed/key field processing
+ affirm(keyFieldIndexes.length == keyFieldCount);
+ affirm(keyFieldCount <= managedFieldCount);
+ affirm(managedFieldNames.length == managedFieldCount);
+ affirm(managedFieldSigs.length == managedFieldCount);
+ affirm(managedFieldMods.length == managedFieldCount);
+ affirm(managedFieldFlags.length == managedFieldCount);
+ affirm(managedFieldCount <= annotatedFieldCount);
+
+ // assign the annotated field arrays
+ if (managedFieldCount == annotatedFieldCount) {
+ // return if the annotated fields are equal to the managed ones
+ annotatedFieldNames = managedFieldNames;
+ annotatedFieldSigs = managedFieldSigs;
+ annotatedFieldMods = managedFieldMods;
+ annotatedFieldFlags = managedFieldFlags;
+ } else {
+ // fill the annotated field arrays with the managed ones
+ annotatedFieldNames = new String[annotatedFieldCount];
+ annotatedFieldSigs = new String[annotatedFieldCount];
+ annotatedFieldMods = new int[annotatedFieldCount];
+ annotatedFieldFlags = new int[annotatedFieldCount];
+ int i = managedFieldCount;
+ System.arraycopy(managedFieldNames, 0, annotatedFieldNames, 0, i);
+ System.arraycopy(managedFieldSigs, 0, annotatedFieldSigs, 0, i);
+ System.arraycopy(managedFieldMods, 0, annotatedFieldMods, 0, i);
+ System.arraycopy(managedFieldFlags, 0, annotatedFieldFlags, 0, i);
+
+ // append the annotated, non-managed fields
+ for (Iterator k = annotatedFieldMap.entrySet().iterator();
+ k.hasNext();) {
+ final Map.Entry entry = (Map.Entry)k.next();
+ final String name = (String)entry.getKey();
+ final ClassField field = (ClassField)entry.getValue();
+ affirm(name.equals(field.name().asString()));
+
+ affirm(!field.isStatic(),
+ ("The managed field " + userClassName + "." + name +
+ " is static."));
+
+ // add field type and Java access modifers
+ annotatedFieldNames[i] = name;
+ annotatedFieldSigs[i] = field.signature().asString();
+ annotatedFieldMods[i] = field.access();
+ annotatedFieldFlags[i] = 0x0; // direct read/write access
+ i++;
+ }
+ affirm(i == annotatedFieldCount);
+ }
+
+ // post conditions
+ affirm(keyFieldIndexes.length == keyFieldCount);
+ affirm(keyFieldCount <= managedFieldCount);
+ affirm(annotatedFieldNames.length == annotatedFieldCount);
+ affirm(annotatedFieldSigs.length == annotatedFieldCount);
+ affirm(annotatedFieldMods.length == annotatedFieldCount);
+ affirm(annotatedFieldFlags.length == annotatedFieldCount);
+ affirm(managedFieldCount <= annotatedFieldCount);
+ }
+
+ /**
+ * Scans the methods of a ClassFile.
+ */
+ private void scanMethods()
+ {
+ // check methods
+ for (final Enumeration e = classFile.methods().elements();
+ e.hasMoreElements();) {
+ final ClassMethod method = (ClassMethod)e.nextElement();
+ final String name = method.name().asString();
+ final String sig = method.signature().asString();
+ affirm(name != null);
+ affirm(sig != null);
+
+ final String key = methodKey(name, sig);
+ affirm(key != null);
+
+ // for non-abstract, non-native methods, map names to class methods
+ if (!method.isAbstract() && !method.isNative()) {
+ final Object m = annotatableMethods.put(key, method);
+ affirm(m == null);
+ }
+
+ // for 'jdo*' like methods, map names to class methods
+ if (name.startsWith("jdo")) {
+ final Object m = jdoLikeMethods.put(key, method);
+ affirm(m == null);
+ continue;
+ }
+
+ // check for a default constructor by name and signature
+ if (name.equals(NameHelper.constructorName())
+ && sig.equals(NameHelper.constructorSig())) {
+ hasDefaultConstructor = true;
+ continue;
+ }
+
+ // check for a static initializer block by name and signature
+ if (name.equals(JAVA_clinit_Name)
+ && sig.equals(JAVA_clinit_Sig)) {
+ hasStaticInitializer = true;
+ continue;
+ }
+
+ // check for method clone() by name and signature
+ if (name.equals(JAVA_Object_clone_Name)
+ && sig.equals(JAVA_Object_clone_Sig)) {
+ hasCloneMethod = true;
+ continue;
+ }
+
+ // check for method writeObject() by name and signature
+ if (name.equals(JAVA_Object_writeObject_Name)
+ && sig.equals(JAVA_Object_writeObject_Sig)) {
+ hasWriteObjectMethod = true;
+ continue;
+ }
+
+ // check for method writeReplace() by name and signature
+ if (name.equals(JAVA_Object_writeReplace_Name)
+ && sig.equals(JAVA_Object_writeReplace_Sig)) {
+ hasWriteReplaceMethod = true;
+ continue;
+ }
+
+ // check for method readObject() by name and signature
+ if (name.equals(JAVA_Object_readObject_Name)
+ && sig.equals(JAVA_Object_readObject_Sig)) {
+ hasReadObjectMethod = true;
+
+ // remove readObject() method from annotation candidates
+ Object m = annotatableMethods.remove(key);
+ affirm(m != null);
+ continue;
+ }
+ }
+
+ // check for a default constructor by name and signature
+ if (hasDefaultConstructor) {
+ env.message(getI18N("enhancer.class_has_default_constructor"));
+ } else {
+ env.message(getI18N("enhancer.class_has_not_default_constructor"));
+ }
+
+ // check for a static initializer block by name and signature
+ if (hasStaticInitializer) {
+ env.message(getI18N("enhancer.class_has_static_initializer"));
+ } else {
+ env.message(getI18N("enhancer.class_has_not_static_initializer"));
+ }
+
+ // check for method clone() by name and signature
+ if (hasCloneMethod) {
+ env.message(getI18N("enhancer.class_has_clone_method"));
+ } else {
+ env.message(getI18N("enhancer.class_has_not_clone_method"));
+ }
+
+ // check for method writeObject() by name and signature
+ if (hasWriteObjectMethod) {
+ env.message(getI18N("enhancer.class_has_writeObject_method"));
+ } else {
+ env.message(getI18N("enhancer.class_has_not_writeObject_method"));
+ }
+
+ // check for method writeReplace() by name and signature
+ if (hasWriteReplaceMethod) {
+ env.message(getI18N("enhancer.class_has_writeReplace_method"));
+ } else {
+ env.message(getI18N("enhancer.class_has_not_writeReplace_method"));
+ }
+
+ // check for method readObject() by name and signature
+ if (hasReadObjectMethod) {
+ env.message(getI18N("enhancer.class_has_readObject_method"));
+ } else {
+ env.message(getI18N("enhancer.class_has_not_readObject_method"));
+ }
+ }
+
+ private void checkGenericAugmentation()
+ {
+ scanForImplementsPC();
+ scanForGenericJDOFields();
+ scanForGenericJDOMethods();
+
+ final boolean all
+ = (hasImplementsPC && hasGenericJDOFields && hasGenericJDOMethods);
+ //^olsen: check
+ final boolean none
+ = !(hasImplementsPC
+ || hasGenericJDOFields || hasGenericJDOMethods);
+
+ if (all ^ none) {
+ hasGenericJDOMembers = hasImplementsPC;
+ env.message(
+ getI18N("enhancer.class_has_generic_jdo_members",
+ String.valueOf(hasGenericJDOMembers)));
+
+ //^olsen: check for specific enhancement
+
+ return;
+ }
+
+ final String key
+ = "enhancer.class_has_inconsistently_declared_jdo_members";
+ if (hasGenericJDOFields && !hasGenericJDOMethods) {
+ env.error(
+ getI18N(key,
+ userClassName,
+ "<generic jdo fields>",
+ "<generic jdo methods>"));
+ } else if (!hasGenericJDOFields && hasGenericJDOMethods) {
+ env.error(
+ getI18N(key,
+ userClassName,
+ "<generic jdo methods>",
+ "<generic jdo fields>"));
+ } else if (!hasGenericJDOFields && !hasGenericJDOMethods) {
+ env.error(
+ getI18N(key,
+ userClassName,
+ "<implements " + JDO_PersistenceCapable_Name + ">",
+ "<generic jdo members>"));
+ } else {
+ env.error(
+ getI18N(key,
+ userClassName,
+ "<generic jdo members>",
+ "<implements " + JDO_PersistenceCapable_Name + ">"));
+ }
+ }
+
+ private void checkSpecificAugmentation()
+ {
+ scanForSpecificJDOFields();
+ scanForSpecificJDOMethods();
+
+ final boolean all
+ = (hasSpecificJDOFields && hasSpecificJDOMethods);
+ //^olsen: check
+ final boolean none
+ = !(hasSpecificJDOFields || hasSpecificJDOMethods);
+
+ if (all ^ none) {
+ hasSpecificJDOMembers = hasSpecificJDOFields;
+ env.message(
+ getI18N("enhancer.class_has_specific_jdo_members",
+ String.valueOf(hasSpecificJDOMembers)));
+ return;
+ }
+
+ final String key
+ = "enhancer.class_has_inconsistently_declared_jdo_members";
+ if (hasSpecificJDOFields && !hasSpecificJDOMethods) {
+ env.error(
+ getI18N(key,
+ userClassName,
+ "<specific jdo fields>",
+ "<specific jdo methods>"));
+ } else {
+ env.error(
+ getI18N(key,
+ userClassName,
+ "<specific jdo methods>",
+ "<specific jdo fields>"));
+ }
+ }
+
+ private void checkCallbackAugmentation()
+ {
+ scanForCallbackJDOMethods();
+ env.message(
+ getI18N("enhancer.class_has_callback_jdo_methods",
+ String.valueOf(hasCallbackJDOMethods)));
+ }
+
+ private void checkPCFeasibility()
+ {
+ if (!hasDefaultConstructor) {
+ env.error(
+ getI18N("enhancer.class_missing_default_constructor",
+ userClassName));
+ }
+ }
+
+ /**
+ * Scans the class for implementing the PC interface.
+ */
+ private void scanForImplementsPC()
+ {
+ hasImplementsPC = false;
+ for (final Iterator ifc = classFile.interfaces().iterator();
+ ifc.hasNext();) {
+ final ConstClass i = (ConstClass)ifc.next();
+ if (i.asString().equals(JDO_PersistenceCapable_Path)) {
+ hasImplementsPC = true;
+ break;
+ }
+ }
+ env.message(
+ getI18N("enhancer.class_implements_jdo_pc",
+ String.valueOf(hasImplementsPC)));
+ }
+
+ /**
+ * Scans for JDO fields of generic augmentation.
+ */
+ private void scanForGenericJDOFields()
+ {
+ // performance shortcut
+ if (jdoLikeFields.isEmpty()) {
+ hasGenericJDOFields = false;
+ env.message(
+ getI18N("enhancer.class_has_generic_jdo_fields",
+ String.valueOf(hasGenericJDOFields)));
+ return;
+ }
+
+ // sets of found/missing 'jdo*' members
+ final Set found = new HashSet(10);
+ final Set missing = new HashSet(10);
+
+ scanJDOField(JDO_PC_jdoStateManager_Name,
+ JDO_PC_jdoStateManager_Sig,
+ JDO_PC_jdoStateManager_Mods,
+ found, missing);
+ scanJDOField(JDO_PC_jdoFlags_Name,
+ JDO_PC_jdoFlags_Sig,
+ JDO_PC_jdoFlags_Mods,
+ found, missing);
+
+ if (found.isEmpty() ^ missing.isEmpty()) {
+ hasGenericJDOFields = missing.isEmpty();
+ env.message(
+ getI18N("enhancer.class_has_generic_jdo_fields",
+ String.valueOf(hasGenericJDOFields)));
+ return;
+ }
+
+ reportInconsistentJDOMembers(found, missing);
+ }
+
+ /**
+ * Scans for JDO methods of generic augmentation.
+ */
+ private void scanForGenericJDOMethods()
+ {
+ // performance shortcut
+ if (jdoLikeMethods.isEmpty()) {
+ hasGenericJDOMethods = false;
+ env.message(
+ getI18N("enhancer.class_has_generic_jdo_methods",
+ String.valueOf(hasGenericJDOMethods)));
+ return;
+ }
+
+ // sets of found/missing 'jdo*' members
+ final Set found = new HashSet(30);
+ final Set missing = new HashSet(30);
+
+ scanJDOMethod(JDO_PC_jdoReplaceStateManager_Name,
+ JDO_PC_jdoReplaceStateManager_Sig,
+ JDO_PC_jdoReplaceStateManager_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoReplaceFlags_Name,
+ JDO_PC_jdoReplaceFlags_Sig,
+ JDO_PC_jdoReplaceFlags_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoGetPersistenceManager_Name,
+ JDO_PC_jdoGetPersistenceManager_Sig,
+ JDO_PC_jdoGetPersistenceManager_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoGetObjectId_Name,
+ JDO_PC_jdoGetObjectId_Sig,
+ JDO_PC_jdoGetObjectId_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoGetTransactionalObjectId_Name,
+ JDO_PC_jdoGetTransactionalObjectId_Sig,
+ JDO_PC_jdoGetTransactionalObjectId_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoIsPersistent_Name,
+ JDO_PC_jdoIsPersistent_Sig,
+ JDO_PC_jdoIsPersistent_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoIsTransactional_Name,
+ JDO_PC_jdoIsTransactional_Sig,
+ JDO_PC_jdoIsTransactional_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoIsNew_Name,
+ JDO_PC_jdoIsNew_Sig,
+ JDO_PC_jdoIsNew_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoIsDeleted_Name,
+ JDO_PC_jdoIsDeleted_Sig,
+ JDO_PC_jdoIsDeleted_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoIsDirty_Name,
+ JDO_PC_jdoIsDirty_Sig,
+ JDO_PC_jdoIsDirty_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoMakeDirty_Name,
+ JDO_PC_jdoMakeDirty_Sig,
+ JDO_PC_jdoMakeDirty_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoPreSerialize_Name,
+ JDO_PC_jdoPreSerialize_Sig,
+ JDO_PC_jdoPreSerialize_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoReplaceFields_Name,
+ JDO_PC_jdoReplaceFields_Sig,
+ JDO_PC_jdoReplaceFields_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoProvideFields_Name,
+ JDO_PC_jdoProvideFields_Sig,
+ JDO_PC_jdoProvideFields_Mods,
+ found, missing);
+
+ if (found.isEmpty() ^ missing.isEmpty()) {
+ hasGenericJDOMethods = missing.isEmpty();
+ env.message(
+ getI18N("enhancer.class_has_generic_jdo_methods",
+ String.valueOf(hasGenericJDOMethods)));
+ return;
+ }
+
+ reportInconsistentJDOMembers(found, missing);
+ }
+
+ /**
+ * Scans for JDO fields of specific augmentation.
+ */
+ private void scanForSpecificJDOFields()
+ {
+ // performance shortcut
+ if (jdoLikeFields.isEmpty()) {
+ hasSpecificJDOFields = false;
+ env.message(
+ getI18N("enhancer.class_has_specific_jdo_fields",
+ String.valueOf(hasSpecificJDOFields)));
+ return;
+ }
+
+ // sets of found/missing 'jdo*' members
+ final Set found = new HashSet(10);
+ final Set missing = new HashSet(10);
+
+ scanJDOField(JDO_PC_jdoInheritedFieldCount_Name,
+ JDO_PC_jdoInheritedFieldCount_Sig,
+ JDO_PC_jdoInheritedFieldCount_Mods,
+ found, missing);
+ scanJDOField(JDO_PC_jdoFieldNames_Name,
+ JDO_PC_jdoFieldNames_Sig,
+ JDO_PC_jdoFieldNames_Mods,
+ found, missing);
+ scanJDOField(JDO_PC_jdoFieldTypes_Name,
+ JDO_PC_jdoFieldTypes_Sig,
+ JDO_PC_jdoFieldTypes_Mods,
+ found, missing);
+ scanJDOField(JDO_PC_jdoFieldFlags_Name,
+ JDO_PC_jdoFieldFlags_Sig,
+ JDO_PC_jdoFieldFlags_Mods,
+ found, missing);
+ scanJDOField(JDO_PC_jdoPersistenceCapableSuperclass_Name,
+ JDO_PC_jdoPersistenceCapableSuperclass_Sig,
+ JDO_PC_jdoPersistenceCapableSuperclass_Mods,
+ found, missing);
+
+ if (found.isEmpty() ^ missing.isEmpty()) {
+ hasSpecificJDOFields = missing.isEmpty();
+ env.message(
+ getI18N("enhancer.class_has_specific_jdo_fields",
+ String.valueOf(hasSpecificJDOFields)));
+ return;
+ }
+
+ reportInconsistentJDOMembers(found, missing);
+ }
+
+ /**
+ * Scans for JDO methods of specific augmentation.
+ */
+ private void scanForSpecificJDOMethods()
+ {
+ // performance shortcut
+ if (jdoLikeMethods.isEmpty()) {
+ hasSpecificJDOMethods = false;
+ env.message(
+ getI18N("enhancer.class_has_specific_jdo_methods",
+ String.valueOf(hasSpecificJDOMethods)));
+ return;
+ }
+
+ // sets of found/missing 'jdo*' members
+ final Set found = new HashSet(30);
+ final Set missing = new HashSet(30);
+
+ scanJDOMethod(JDO_PC_jdoGetManagedFieldCount_Name,
+ JDO_PC_jdoGetManagedFieldCount_Sig,
+ JDO_PC_jdoGetManagedFieldCount_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoNewInstance_Name,
+ JDO_PC_jdoNewInstance_Sig,
+ JDO_PC_jdoNewInstance_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoNewInstance_Name,
+ JDO_PC_jdoNewInstance_Sig,
+ JDO_PC_jdoNewInstance_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoNewObjectIdInstance_Name,
+ JDO_PC_jdoNewObjectIdInstance_Sig,
+ JDO_PC_jdoNewObjectIdInstance_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoNewObjectIdInstance_Name,
+ JDO_PC_jdoNewObjectIdInstance_Sig,
+ JDO_PC_jdoNewObjectIdInstance_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoCopyKeyFieldsToObjectId_Name,
+ JDO_PC_jdoCopyKeyFieldsToObjectId_Sig,
+ JDO_PC_jdoCopyKeyFieldsToObjectId_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoCopyKeyFieldsToObjectId_OIFS_Name,
+ JDO_PC_jdoCopyKeyFieldsToObjectId_OIFS_Sig,
+ JDO_PC_jdoCopyKeyFieldsToObjectId_OIFS_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoCopyKeyFieldsFromObjectId_OIFC_Name,
+ JDO_PC_jdoCopyKeyFieldsFromObjectId_OIFC_Sig,
+ JDO_PC_jdoCopyKeyFieldsFromObjectId_OIFC_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoReplaceField_Name,
+ JDO_PC_jdoReplaceField_Sig,
+ JDO_PC_jdoReplaceField_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoProvideField_Name,
+ JDO_PC_jdoProvideField_Sig,
+ JDO_PC_jdoProvideField_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoCopyFields_Name,
+ JDO_PC_jdoCopyFields_Sig,
+ JDO_PC_jdoCopyFields_Mods,
+ found, missing);
+ scanJDOMethod(JDO_PC_jdoCopyField_Name,
+ JDONameHelper.getJDO_PC_jdoCopyField_Sig(className),
+ JDO_PC_jdoCopyField_Mods,
+ found, missing);
+
+ if (found.isEmpty() ^ missing.isEmpty()) {
+ hasSpecificJDOMethods = missing.isEmpty();
+ env.message(
+ getI18N("enhancer.class_has_specific_jdo_methods",
+ String.valueOf(hasSpecificJDOMethods)));
+ return;
+ }
+
+ reportInconsistentJDOMembers(found, missing);
+ }
+
+ /**
+ * Scans for JDO methods of generic augmentation.
+ */
+ private void scanForCallbackJDOMethods()
+ {
+ // performance shortcut
+ if (jdoLikeMethods.isEmpty()) {
+ hasCallbackJDOMethods = false;
+ env.message(
+ getI18N("enhancer.class_has_callback_jdo_methods",
+ String.valueOf(hasCallbackJDOMethods)));
+ return;
+ }
+
+ // sets of found/missing 'jdo*' members
+ final Set found = new HashSet(30);
+ final Set missing = new HashSet(30);
+ final boolean annotatable = true;
+
+ scanJDOMethod(JDO_IC_jdoPostLoad_Name,
+ JDO_IC_jdoPostLoad_Sig,
+ JDO_IC_jdoPostLoad_Mods,
+ found, missing, !annotatable);
+
+ scanJDOMethod(JDO_IC_jdoPreStore_Name,
+ JDO_IC_jdoPreStore_Sig,
+ JDO_IC_jdoPreStore_Mods,
+ found, missing, annotatable);
+
+ scanJDOMethod(JDO_IC_jdoPreClear_Name,
+ JDO_IC_jdoPreClear_Sig,
+ JDO_IC_jdoPreClear_Mods,
+ found, missing, !annotatable);
+
+ scanJDOMethod(JDO_IC_jdoPreDelete_Name,
+ JDO_IC_jdoPreDelete_Sig,
+ JDO_IC_jdoPreDelete_Mods,
+ found, missing, annotatable);
+
+ // no requirement to check for 'missing' methods
+ if (!found.isEmpty()) {
+ hasCallbackJDOMethods = true;
+ env.message(
+ getI18N("enhancer.class_has_callback_jdo_methods",
+ String.valueOf(hasCallbackJDOMethods)));
+ }
+ }
+
+ /**
+ * Verifies a JDO field signature.
+ */
+ private void scanJDOField(String fieldName,
+ String expectedSig,
+ int expectedMods,
+ Set found,
+ Set missing)
+ {
+ final ClassField field = (ClassField)jdoLikeFields.get(fieldName);
+ if (field == null) {
+ missing.add(fieldName);
+ return;
+ }
+ found.add(fieldName);
+
+ final String foundSig = field.signature().asString();
+ final int foundMods = field.access();
+ if (!expectedSig.equals(foundSig) || expectedMods != foundMods) {
+ env.error(
+ getI18N("enhancer.class_has_illegally_declared_jdo_member",
+ new Object[]{ userClassName,
+ fieldName,
+ expectedSig,
+ foundSig,
+ new Integer(expectedMods),
+ new Integer(foundMods) }));
+ }
+ }
+
+ /**
+ * Verifies a JDO method signature.
+ */
+ private void scanJDOMethod(String methodName,
+ String expectedSig,
+ int expectedMods,
+ Set found,
+ Set missing)
+ {
+ scanJDOMethod(methodName, expectedSig, expectedMods,
+ found, missing, true);
+ }
+
+ /**
+ * Verifies a JDO method signature.
+ */
+ private void scanJDOMethod(String methodName,
+ String expectedSig,
+ int expectedMods,
+ Set found,
+ Set missing,
+ boolean annotatable)
+ {
+ final String key = methodKey(methodName, expectedSig);
+ final ClassMethod method = (ClassMethod)jdoLikeMethods.get(key);
+ if (method == null) {
+ missing.add(key);
+ return;
+ }
+ found.add(key);
+
+ final String foundSig = method.signature().asString();
+ final int foundMods = method.access();
+ if (!expectedSig.equals(foundSig) || expectedMods != foundMods) {
+ env.error(
+ getI18N("enhancer.class_has_illegally_declared_jdo_member",
+ new Object[]{ userClassName,
+ methodName,
+ expectedSig,
+ foundSig,
+ new Integer(expectedMods),
+ new Integer(foundMods) }));
+ }
+
+ // remove jdo method from annotation candidates
+ if (!annotatable) {
+ Object m = annotatableMethods.remove(key);
+ affirm(m != null);
+ }
+ }
+
+ /**
+ * Reports an error for some found/missing JDO fields or methods.
+ */
+ private void reportInconsistentJDOMembers(Set found,
+ Set missing)
+ {
+ final Iterator fi = found.iterator();
+ final StringBuffer f = new StringBuffer((String)fi.next());
+ while (fi.hasNext()) {
+ f.append(", " + fi.next());
+ }
+
+ final Iterator mi = found.iterator();
+ final StringBuffer m = new StringBuffer((String)mi.next());
+ while (mi.hasNext()) {
+ m.append(", " + mi.next());
+ }
+
+ env.error(
+ getI18N("enhancer.class_has_inconsistently_declared_jdo_members",
+ userClassName, f.toString(), m.toString()));
+ }
+
+ // ----------------------------------------------------------------------
+
+ static private String methodKey(String name,
+ String sig)
+ {
+ affirm(name != null);
+ affirm(sig != null && sig.charAt(0) == '(' && sig.indexOf(')') > 0);
+ final String parms = sig.substring(0, sig.indexOf(')') + 1);
+ return (name + parms);
+ }
+}
|