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 [3/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/OptionSet.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/OptionSet.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/OptionSet.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/OptionSet.java Sun May 22 10:55:51 2005
@@ -0,0 +1,715 @@
+/*
+ * 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;
+
+import java.io.PrintWriter;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Properties;
+
+
+/**
+ * Represents a set of options a program may support.
+ *
+ * @author Martin Zaun
+ */
+public class OptionSet
+    extends LogSupport
+{
+    // return values of parse/check methods
+    static public final int OK = 0;
+    static public final int USAGE_ERROR = -1;
+
+    // command-line option prefixes
+    static public final String prefix = "-";
+    static public final String lprefix = "--";
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * The base class of all option types.
+     */
+    static public abstract class Option
+    {
+        /**
+         * The set the option is registered with.
+         */
+        protected OptionSet set;
+
+        /**
+         * The long form name of this option.
+         */
+        public final String name;
+
+        /**
+         * The short form name of this option.
+         */
+        public final String abbrev;
+
+        /**
+         * A description of this option.
+         */
+        public final String descr;
+
+        /**
+         * Creates an instance.
+         */
+        public Option(String name,
+                      String abbrev,
+                      String descr)
+        {
+            affirm(name != null);
+            this.name = name;
+            this.abbrev = abbrev;
+            this.descr = descr;            
+        }
+
+        /**
+         * Parse this option for arguments it may require.
+         */
+        abstract public int parse(Iterator i);
+
+        /**
+         * Returns a <code>String</code> representation of this option's
+         * value for printing.
+         */
+        abstract public String asNameValue();
+
+        /**
+         * Returns a usage description of this option.
+         */
+        public String asUsageHelp()
+        {
+            String abbr = (abbrev == null ? "   " : prefix + abbrev + "|");
+            return (abbr + lprefix + name + " " + descr);
+        }
+    }
+
+    /**
+     * An option that always causes a USAGE_ERROR when parsed (used for
+     * '-h|--help' kind of options).
+     */
+    static public class HelpOption extends Option
+    {
+        /**
+         * Creates an instance.
+         */
+        public HelpOption(String name,
+                          String abbrev,
+                          String descr)
+        {
+            super(name, abbrev, descr);
+        }
+        
+        public int parse(Iterator i) 
+        {
+            return USAGE_ERROR;
+        }
+
+        public String asNameValue()
+        {
+            return ("help = false");
+        }
+    }
+
+    /**
+     * An option representing a boolean flag.
+     */
+    static public class FlagOption extends Option
+    {
+        /**
+         * The default value for this option.
+         */
+        public final boolean deflt;
+
+        /**
+         * The value of this option.
+         */
+        public boolean value;
+
+        /**
+         * Creates an instance.
+         */
+        public FlagOption(String name,
+                          String abbrev,
+                          String descr)
+        {
+            this(name, abbrev, descr, false);
+        }
+
+        /**
+         * Creates an instance.
+         */
+        public FlagOption(String name,
+                          String abbrev,
+                          String descr,
+                          boolean deflt)
+        {
+            super(name, abbrev, descr);
+            this.deflt = deflt;
+            this.value = deflt;
+        }
+
+        public int parse(Iterator i) 
+        {
+            if (value != deflt) {
+                set.printUsageError("Repeated option: "
+                                    + prefix + abbrev + "/" + lprefix + name);
+                return USAGE_ERROR;
+            }
+            value = true;
+            return OK;
+        }
+
+        public String asNameValue()
+        {
+            return (name + " = " + String.valueOf(value));
+        }
+    }
+
+    /**
+     * An option representing a <code>int</code> value.
+     */
+    static public class IntOption extends Option
+    {
+        /**
+         * The default value for this option.
+         */
+        public final int deflt;
+
+        /**
+         * The value of this option.
+         */
+        public int value;
+
+        /**
+         * Creates an instance.
+         */
+        public IntOption(String name,
+                         String abbrev,
+                         String descr)
+        {
+            this(name, abbrev, descr, 0);
+        }
+
+        /**
+         * Creates an instance.
+         */
+        public IntOption(String name,
+                         String abbrev,
+                         String descr,
+                         int deflt)
+        {
+            super(name, abbrev, descr);
+            this.deflt = deflt;
+            this.value = deflt;
+        }
+
+        public int parse(Iterator i) 
+        {
+            if (value != deflt) {
+                set.printUsageError("Repeated option: "
+                                    + prefix + abbrev + "/" + lprefix + name);
+                return USAGE_ERROR;
+            }
+            if (!i.hasNext()) {
+                set.printUsageError("Missing argument to option: "
+                                    + prefix + abbrev + "/" + lprefix + name);
+                return USAGE_ERROR;
+            }
+            try {
+                value = Integer.valueOf((String)i.next()).intValue();
+            } catch (NumberFormatException ex) {
+                set.printUsageError("Illegal argument to option: "
+                                    + prefix + abbrev + "/" + lprefix + name);
+                return USAGE_ERROR;
+            }
+            return OK;
+        }
+
+        public String asNameValue()
+        {
+            return (name + " = " + String.valueOf(value));
+        }
+    }
+
+    /**
+     * An option representing a <code>String</code> value.
+     */
+    static public class StringOption extends Option
+    {
+        /**
+         * The default value for this option.
+         */
+        public final String deflt;
+
+        /**
+         * The value of this option.
+         */
+        public String value;
+
+        /**
+         * Creates an instance.
+         */
+        public StringOption(String name,
+                            String abbrev,
+                            String descr)
+        {
+            this(name, abbrev, descr, null);
+        }
+
+        /**
+         * Creates an instance.
+         */
+        public StringOption(String name,
+                            String abbrev,
+                            String descr,
+                            String deflt)
+        {
+            super(name, abbrev, descr);
+            this.deflt = deflt;
+            this.value = deflt;
+        }
+
+        public int parse(Iterator i) 
+        {
+            if (value != deflt) {
+                set.printUsageError("Repeated option: "
+                                    + prefix + abbrev + "/" + lprefix + name);
+                return USAGE_ERROR;
+            }
+            if (!i.hasNext()) {
+                set.printUsageError("Missing argument to option: "
+                                    + prefix + abbrev + "/" + lprefix + name);
+                return USAGE_ERROR;
+            }
+            value = (String)i.next();
+            if (value.startsWith(prefix)) {
+                set.printUsageError("Missing argument to option: "
+                                    + prefix + abbrev + "/" + lprefix + name);
+                return USAGE_ERROR;
+            }
+            return OK;
+        }
+
+        public String asNameValue()
+        {
+            return (name + " = " + String.valueOf(value));
+        }
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * The list of registered options.
+     */
+    protected final List options = new ArrayList();
+
+    /**
+     * Maps the option's long form against option instances.
+     */
+    protected final Map names = new HashMap();
+
+    /**
+     * Maps the option's short form against option instances.
+     */
+    protected final Map abbrevs = new HashMap();
+
+    /**
+     * The collected arguments.
+     */
+    protected final List arguments = new ArrayList();
+
+    /**
+     * Usage printout.
+     */
+    public String usageHeader
+        = "Usage: <options>.. <arguments>..";
+
+    /**
+     * Usage printout.
+     */
+    public String optionsHeader
+        = "Options:";
+
+    /**
+     * Usage printout.
+     */
+    public String argumentsHeader
+        = "Arguments:";
+
+    /**
+     * Usage printout.
+     */
+    public String returnHeader
+        = "Returns: A non-zero value in case of errors.";
+
+    /**
+     * Usage printout.
+     */
+    public String indent
+        = "    ";
+
+    /**
+     * Creates an instance.
+     */
+    public OptionSet(PrintWriter out,
+                     PrintWriter err) 
+    {
+        super(out, err);
+    }
+
+    /**
+     * Creates an instance.
+     */
+    public OptionSet(PrintWriter out,
+                     PrintWriter err,
+                     String usageHeader,
+                     String optionsHeader,
+                     String argumentsHeader,
+                     String returnHeader,
+                     String indent)
+    {
+        this(out, err);
+        this.usageHeader = usageHeader;
+        this.optionsHeader = optionsHeader;
+        this.argumentsHeader = argumentsHeader;
+        this.returnHeader = returnHeader;
+        this.indent = indent;
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Registers an option with the set.
+     */
+    public void register(Option option) 
+    {
+        affirm(option != null);
+        option.set = this;
+        options.add(option);
+
+        affirm(option.name != null);
+        Object obj = names.put(lprefix + option.name, option);
+        affirm(obj == null, "Option already registered: " + option.name);
+
+        if (option.abbrev != null) {
+            obj = abbrevs.put(prefix + option.abbrev, option);
+            affirm(obj == null, "Option already registered: " + option.name);
+        }
+    }
+
+    /**
+     * Creates and registers an option representing a usage-help request.
+     */
+    public HelpOption createHelpOption(String name,
+                                       String abbrev,
+                                       String descr)
+    {
+        final HelpOption opt = new HelpOption(name, abbrev, descr);
+        register(opt);
+        return opt;
+    }
+
+    /**
+     * Creates and registers an option representing a boolean flag.
+     */
+    public FlagOption createFlagOption(String name,
+                                       String abbrev,
+                                       String descr)
+    {
+        final FlagOption opt = new FlagOption(name, abbrev, descr);
+        register(opt);
+        return opt;
+    }
+
+    /**
+     * Creates and registers an option representing a boolean flag.
+     */
+    public FlagOption createFlagOption(String name,
+                                       String abbrev,
+                                       String descr,
+                                       boolean deflt)
+    {
+        final FlagOption opt = new FlagOption(name, abbrev, descr, deflt);
+        register(opt);
+        return opt;
+    }
+
+    /**
+     * Creates and registers an option representing a <code>int</code>
+     * value.
+     */
+    public IntOption createIntOption(String name,
+                                     String abbrev,
+                                     String descr)
+    {
+        final IntOption opt = new IntOption(name, abbrev, descr);
+        register(opt);
+        return opt;
+    }
+
+    /**
+     * Creates and registers an option representing a <code>int</code>
+     * value.
+     */
+    public IntOption createIntOption(String name,
+                                     String abbrev,
+                                     String descr,
+                                     int deflt)
+    {
+        final IntOption opt = new IntOption(name, abbrev, descr, deflt);
+        register(opt);
+        return opt;
+    }
+
+    /**
+     * Creates and registers an option representing a <code>String</code>
+     * value.
+     */
+    public StringOption createStringOption(String name,
+                                           String abbrev,
+                                           String descr)
+    {
+        final StringOption opt = new StringOption(name, abbrev, descr);
+        register(opt);
+        return opt;
+    }
+
+    /**
+     * Creates and registers an option representing a <code>String</code>
+     * value.
+     */
+    public StringOption createStringOption(String name,
+                                           String abbrev,
+                                           String descr,
+                                           String deflt)
+    {
+        final StringOption opt
+            = new StringOption(name, abbrev, descr, deflt);
+        register(opt);
+        return opt;
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Parses options and arguments.
+     */
+    public int parse(String[] argv)
+    {
+        affirm(argv != null);
+        for (Iterator i = Arrays.asList(argv).iterator(); i.hasNext();) {
+            final String arg = (String)i.next();
+
+            // ignore empty arguments
+            if (arg == null || arg.length() == 0) {
+                //println("Ignoring empty command line argument.");
+                continue;
+            }
+
+            // collect as argument if not option
+            if (!arg.startsWith(prefix)) {
+                arguments.add(arg);
+                continue;                
+            }
+
+            // lookup option by short and long form
+            Option option = (Option)abbrevs.get(arg);
+            if (option == null) {
+                option = (Option)names.get(arg);
+            }
+
+            // return if option still not recognized
+            if (option == null) {
+                printlnErr("Unrecognized option: " + arg);
+                return USAGE_ERROR;
+            }
+
+            // parse option for arguments
+            int res = option.parse(i);
+            if (res != OK) {
+                return res;
+            }
+        }
+        return OK;
+    }
+
+    /**
+     * Checks options and arguments.
+     */
+    public int check()
+    {
+        return OK;
+    }
+
+    /**
+     * Parse and check options and arguments.
+     */
+    public int process(String[] args)
+    {
+        int res = OK;
+        if ((res = parse(args)) != OK) {
+            printUsage();
+            return res;
+        }
+        if ((res = check()) != OK) {
+            printUsage();
+            return res;
+        }
+        return res;
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Print a usage error message to System.err.
+     */
+    public void printUsageError(String msg)
+    {
+        printlnErr("USAGE ERROR: " + msg);
+    }
+    
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printUsage()
+    {
+        println();
+        printUsageHeader();
+        printOptionHeader();
+        printOptionUsage();
+        printArgumentHeader();
+        printArgumentUsage();
+        printReturnHeader();
+        printReturnUsage();
+    }
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printUsageHeader()
+    {
+        printlnErr(usageHeader);
+    }
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printOptionHeader()
+    {
+        printlnErr();
+        printlnErr(optionsHeader);
+    }
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printOptionUsage()
+    {
+        for (Iterator i = options.iterator(); i.hasNext();) {
+            printlnErr(indent + ((Option)i.next()).asUsageHelp());
+        }
+    }
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printArgumentHeader()
+    {
+        printlnErr();
+        printlnErr(argumentsHeader);
+    }
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printArgumentUsage()
+    {}
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printReturnHeader()
+    {
+        printlnErr();
+        printlnErr(returnHeader);
+    }
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printReturnUsage()
+    {}
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Print options and arguments.
+     */
+    public void printAll()
+    {
+        printOptions();
+        printArguments();
+    }
+
+    /**
+     * Print options.
+     */
+    public void printOptions()
+    {
+        println();
+        println(optionsHeader);
+        for (Iterator i = options.iterator(); i.hasNext();) {
+            println(indent + ((Option)i.next()).asNameValue());
+        }
+    }
+    
+    /**
+     * Print arguments.
+     */
+    public void printArguments()
+    {
+        println();
+        println(argumentsHeader);
+        print(indent);
+        for (Iterator i = arguments.iterator(); i.hasNext();) {
+            print(" " + i.next());
+        }
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Tests the class.
+     */
+    static public void main(String[] args)
+    {
+        final PrintWriter out = new PrintWriter(System.out, true);
+        out.println("--> OptionSet.main()");
+        final OptionSet options = new OptionSet(out, out);
+        out.println("    options.process() ...");
+        int res = options.process(args);
+        out.println("    return value: " + res);
+        out.println("<-- OptionSet.main()");
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/OutputStreamWrapper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/OutputStreamWrapper.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/OutputStreamWrapper.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/OutputStreamWrapper.java Sun May 22 10:55:51 2005
@@ -0,0 +1,85 @@
+/*
+ * 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;
+
+import java.io.OutputStream;
+
+/**
+ *  This class serves as a wrapper for an output stream of a class file. The
+ *  stream is passed as a parameter to the byte code enhancer, that can
+ *  sets the classname of the written Java class to the wrapper.
+ *  <br>
+ *  This wrapper is necessary to determine the classname outside the enhancer,
+ *  after the class has been enhanced, since do do not always know the
+ *  classname of an opened input stream.
+ *
+ */
+public class OutputStreamWrapper
+{
+    /**
+     *  The wrapped output stream.
+     */
+    private OutputStream out;
+
+    /**
+     *  The classname of the written Java class. This parameter
+     *  is set by the enhancer.
+     */
+    private String className = null;
+
+    /**
+     *  Constructs a new object.
+     *
+     *  @param  out  The output stream to wrap.
+     */
+    public OutputStreamWrapper(OutputStream out)
+    {
+        this.out = out;
+    }
+
+    /**
+     *  Gets the wrapped output stream.
+     *
+     *  @return The wrapped output stream.
+     */
+    public final OutputStream getStream()
+    {
+        return out;
+    }
+
+    /**
+     *  Gets the classname of the written Java class. This method should be
+     *  called after the class has been enhanced.
+     *
+     *  @return  The name of the written Java class.
+     */
+    public final String getClassName()
+    {
+        return className;
+    }
+
+    /**
+     *  Sets the name of the written Java class. This method should be called
+     *  by the enhancer.
+     *
+     *  @param  classname  The name of the Java class.
+     */
+    public final void setClassName(String classname)
+    {
+        this.className = classname;
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/PersistenceLauncher.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/PersistenceLauncher.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/PersistenceLauncher.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/PersistenceLauncher.java Sun May 22 10:55:51 2005
@@ -0,0 +1,284 @@
+/*
+ * 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;
+
+import java.util.Properties;
+
+import java.io.PrintWriter;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.jdo.impl.enhancer.util.Support;
+
+
+
+/**
+ * Application launcher for persistence-capable classes.
+ *
+ * @author Martin Zaun
+ */
+public class PersistenceLauncher {
+
+    // chose whether to separate or join out and err channels
+    //static private final PrintWriter err = new PrintWriter(System.err, true);
+    static private final PrintWriter err = new PrintWriter(System.out, true);
+    static private final PrintWriter out = new PrintWriter(System.out, true);
+    static private final String prefix = "PersistenceLauncher.main() : ";
+
+    /**
+     * Creates new PersistenceLauncher.
+     */
+    private PersistenceLauncher() {
+    }
+
+    /**
+     * Prints usage message.
+     */
+    static void usage()
+    {
+        out.flush();
+        err.println("PersistenceLauncher:");
+        err.println("    usage: <options> ... <target class name> <args> ...");
+        err.println("    options:");
+        err.println("           -h | --help");
+        err.println("           -n | --noEnhancement");
+        err.println("           -q | --quiet");
+        err.println("           -w | --warn");
+        err.println("           -d | --debug");
+        err.println("           -t | --timing");
+        err.println("    class names have to be fully qualified");
+        err.println("done.");
+        err.println();
+        err.flush();
+    }
+
+    /**
+     * Creates a class loader and launches a target class.
+     * @param args the command line arguments
+     */
+    public static void main(String[] args)
+        throws ClassNotFoundException,
+        NoSuchMethodException,
+        SecurityException,
+        IllegalAccessException,
+        IllegalArgumentException,
+        InvocationTargetException {
+/*
+        message("property PersistenceExecutor.TAG_REPOSITORY = "
+                + System.getProperty("PersistenceExecutor.TAG_REPOSITORY"));
+        message("property PersistenceExecutor.TAG_CLASSPATH = "
+                + System.getProperty("PersistenceExecutor.TAG_CLASSPATH"));
+        message("property PersistenceExecutor.TAG_LIBRARY = "
+                + System.getProperty("PersistenceExecutor.TAG_LIBRARY"));
+        message("property PersistenceExecutor.TAG_CLASSNAME = "
+                + System.getProperty("PersistenceExecutor.TAG_CLASSNAME"));
+*/
+
+        // get launcher options
+        final String classpath = System.getProperty("java.class.path");
+        boolean noEnhancement = false;
+        boolean debug = false;
+        boolean timing = false;
+        Properties enhancerSettings = new Properties();
+        String targetClassname = null;
+        String[] targetClassArgs = null;
+        for (int i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.equals("-h")
+                || arg.equals("--help")) {
+                usage();
+
+                // exit gently
+                return;
+            }
+            if (arg.equals("-n")
+                || arg.equals("--noEnhancement")) {
+                noEnhancement = false;
+                continue;
+            }
+            if (arg.equals("-t")
+                || arg.equals("--timing")) {
+                timing = true;
+                enhancerSettings.setProperty(EnhancerClassLoader.DO_TIMING_STATISTICS,
+                                             "true");
+                continue;
+            }
+            if (arg.equals("-d")
+                || arg.equals("--debug")) {
+                debug = true;
+                enhancerSettings.setProperty(EnhancerClassLoader.VERBOSE_LEVEL,
+                                             EnhancerClassLoader.VERBOSE_LEVEL_DEBUG);
+                continue;
+            }
+            if (arg.equals("-w")
+                || arg.equals("--warn")) {
+                debug = false;
+                enhancerSettings.setProperty(EnhancerClassLoader.VERBOSE_LEVEL,
+                                             EnhancerClassLoader.VERBOSE_LEVEL_WARN);
+                continue;
+            }
+            if (arg.equals("-q")
+                || arg.equals("--quiet")) {
+                debug = false;
+                enhancerSettings.setProperty(EnhancerClassLoader.VERBOSE_LEVEL,
+                                             EnhancerClassLoader.VERBOSE_LEVEL_QUIET);
+                continue;
+            }
+
+            // get target class name
+            targetClassname = arg;
+
+            // copy remaining arguments and leave loop
+            i++;
+            final int length = args.length - i;
+            targetClassArgs = new String[length];
+            System.arraycopy(args, i, targetClassArgs, 0, length);
+            break;
+        }
+
+        // debugging oputput
+        if (debug) {
+            out.println(prefix + "...");
+            out.println("settings and arguments:");
+            out.println("    classpath = " + classpath);
+            out.println("    noEnhancement = " + noEnhancement);
+            out.println("    debug = " + debug);
+            out.println("    enhancerSettings = {");
+            enhancerSettings.list(out);
+            out.println("    }");
+            out.println("    targetClassname = " + targetClassname);
+            out.print("    targetClassArgs = { ");
+            for (int i = 0; i < targetClassArgs.length; i++) {
+                out.print(targetClassArgs[i] + " ");
+            }
+            out.println("}");
+        }
+
+        // check options
+        if (targetClassname == null) {
+            usage();
+            throw new IllegalArgumentException("targetClassname == null");
+        }
+
+        // get class loader
+        final ClassLoader loader;
+        if (noEnhancement) {
+            if (debug) {
+                out.println(prefix + "using system class loader");
+            }
+            //out.println("using system class loader");
+            loader = PersistenceLauncher.class.getClassLoader();
+        } else {
+            if (debug) {
+                out.println(prefix + "creating enhancer class loader");
+            }
+            final Properties settings = enhancerSettings;
+            final PrintWriter out = PersistenceLauncher.out;
+            loader = new EnhancerClassLoader(classpath, settings, out);
+        }
+
+        // get target class' main method
+        Class clazz;
+        Method main;
+        try {
+            final String mname = "main";
+            final Class[] mparams = new Class[]{ String[].class };
+            final boolean init = true;
+            if (debug) {
+                out.println(prefix + "getting method "
+                            + targetClassname + "." + mname + "(String[])");
+            }
+            clazz = Class.forName(targetClassname, init, loader);
+            main = clazz.getDeclaredMethod(mname, mparams);
+        } catch (ClassNotFoundException e) {
+            // log exception only
+            if (debug) {
+                out.flush();
+                err.println("PersistenceLauncher: EXCEPTION SEEN: " + e);
+                e.printStackTrace(err);
+                err.flush();
+            }
+            throw e;
+        } catch (NoSuchMethodException e) {
+            // log exception only
+            if (debug) {
+                out.flush();
+                err.println("PersistenceLauncher: EXCEPTION SEEN: " + e);
+                e.printStackTrace(err);
+                err.flush();
+            }
+            throw e;
+        } catch (SecurityException e) {
+            // log exception only
+            if (debug) {
+                out.flush();
+                err.println("PersistenceLauncher: EXCEPTION SEEN: " + e);
+                e.printStackTrace(err);
+                err.flush();
+            }
+            throw e;
+        }
+
+        // invoke target class' main method
+        try {
+            final Object[] margs = new Object[]{ targetClassArgs };
+            if (debug) {
+                out.println("invoking method " + clazz.getName()
+                            + "." + main.getName() + "(String[])");
+            }
+            main.invoke(null, margs);
+        } catch (IllegalAccessException e) {
+            // log exception only
+            if (debug) {
+                out.flush();
+                err.println("PersistenceLauncher: EXCEPTION SEEN: " + e);
+                e.printStackTrace(err);
+                err.flush();
+            }
+            throw e;
+        } catch (IllegalArgumentException e) {
+            // log exception only
+            if (debug) {
+                out.flush();
+                err.println("PersistenceLauncher: EXCEPTION SEEN: " + e);
+                e.printStackTrace(err);
+                err.flush();
+            }
+            throw e;
+        } catch (InvocationTargetException e) {
+            // log exception only
+            if (debug) {
+                out.flush();
+                err.println("PersistenceLauncher: EXCEPTION SEEN: " + e);
+                e.printStackTrace(err);
+                err.flush();
+            }
+            throw e;
+        } finally {
+            if (timing) {
+                Support.timer.print();
+            }
+        }
+
+        if (debug) {
+            out.println(prefix + "done.");
+            out.flush();
+            err.flush();
+        }
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AnnotatedClassAttribute.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AnnotatedClassAttribute.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AnnotatedClassAttribute.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AnnotatedClassAttribute.java Sun May 22 10:55:51 2005
@@ -0,0 +1,132 @@
+/*
+ * 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.*;
+
+/**
+ * AnnotatedClassAttribute represents a class level attribute
+ * class file which identifies the level of annotation of the class.
+ */
+public class AnnotatedClassAttribute extends ClassAttribute {
+
+    /* The expected attribute name */
+    public final static String expectedAttrName = "filter.annotatedClass";
+
+    /* The expected attribute version */
+    public final static short expectedAttrVersion = 1;
+
+    /* Bit mask indicating that the class was filter generated */
+    public final static short generatedFlag = 0x1;
+
+    /* Bit mask indicating that the class was filter annotated */
+    public final static short annotatedFlag = 0x2;
+
+    /* Bit mask indicating that the class was "repackaged" or similarly
+     * modified */
+    public final static short modifiedFlag = 0x4;
+
+    /* The version of the attribute */
+    private short attrVersion;
+
+    /* Flags associated with the annotation */
+    private short annotationFlags;
+
+    /* The modification date of the class file at the time of modification */
+    private long classModTime;
+
+    /* The date of the annotation */
+    private long classAnnotationTime;
+
+    /* public accessors */
+
+    public short getVersion() {
+        return attrVersion;
+    }
+
+    public void setVersion(short version) {
+        attrVersion = version;
+    }
+
+    public short getFlags() {
+        return annotationFlags;
+    }
+
+    public void setFlags(short flags) {
+        annotationFlags = flags;
+    }
+
+    public long getModTime() {
+        return classModTime;
+    }
+
+    public void setModTime(long time) {
+        classModTime = time;
+    }
+
+    public long getAnnotationTime() {
+        return classAnnotationTime;
+    }
+
+    public void setAnnotationTime(long time) {
+        classAnnotationTime = time;
+    }
+
+    /**
+     * Constructor
+     */
+    public AnnotatedClassAttribute(
+	ConstUtf8 nameAttr, short version, short annFlags,
+	long modTime, long annTime) {
+        super(nameAttr);
+        attrVersion = version;
+        annotationFlags = annFlags;
+        classModTime = modTime;
+        classAnnotationTime = annTime;
+    }
+
+    /* package local methods */
+
+    static AnnotatedClassAttribute read(
+	ConstUtf8 attrName, DataInputStream data, ConstantPool pool)
+        throws IOException {
+        short version = data.readShort();
+        short annFlags = data.readShort();
+        long modTime = data.readLong();
+        long annTime = data.readLong();
+        return  new AnnotatedClassAttribute(attrName, version, annFlags,
+                                            modTime, annTime);
+    }
+
+    void write(DataOutputStream out) throws IOException {
+        out.writeShort(attrName().getIndex());
+        out.writeShort(20);
+        out.writeShort(attrVersion);
+        out.writeShort(annotationFlags);
+        out.writeLong(classModTime);
+        out.writeLong(classAnnotationTime);
+    }
+
+    void print(PrintStream out, int indent) {
+        ClassPrint.spaces(out, indent);
+        out.println("version: " + attrVersion);
+        out.println(" flags: " + annotationFlags);
+        out.println(" modTime: " + classModTime);
+        out.println(" annTime: " + classAnnotationTime);
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AnnotatedMethodAttribute.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AnnotatedMethodAttribute.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AnnotatedMethodAttribute.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AnnotatedMethodAttribute.java Sun May 22 10:55:51 2005
@@ -0,0 +1,140 @@
+/*
+ * 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.*;
+
+/**
+ * AnnotatedMethodAttribute represents a class level attribute
+ * class file which identifies the level of annotation of the class.
+ */
+public class AnnotatedMethodAttribute extends ClassAttribute {
+
+    /* The expected attribute name */
+    public final static String expectedAttrName = "filter.annotatedMethod";
+
+    /* The expected attribute version */
+    public final static short expectedAttrVersion = 1;
+
+    /* Bit mask indicating that the class was filter generated */
+    public final static short generatedFlag = 0x1;
+
+    /* Bit mask indicating that the class was filter annotated */
+    public final static short annotatedFlag = 0x2;
+
+    /* Bit mask indicating that the class was "repackaged" */
+    public final static short modifiedFlag = 0x4;
+
+    /* The version of the attribute */
+    private short attrVersion;
+
+    /* Flags associated with the annotation */
+    private short annotationFlags;
+
+    /* list of targets in the code sequence delimiting inserted instruction
+     * sequences.  Even index targets are a range start (inclusive) and odd
+     * targets represent a range end (exclusive) */
+    private InsnTarget annotationRanges[];
+
+    /* public accessors */
+
+    public short getVersion() {
+        return attrVersion;
+    }
+
+    public void setVersion(short version) {
+        attrVersion = version;
+    }
+
+    public short getFlags() {
+        return annotationFlags;
+    }
+
+    public void setFlags(short flags) {
+        annotationFlags = flags;
+    }
+
+    public InsnTarget[] getAnnotationRanges() {
+        return annotationRanges;
+    }
+
+    public void setAnnotationRanges(InsnTarget[] ranges) {
+        annotationRanges = ranges;
+    }
+
+    /**
+     * Constructor
+     */
+    public AnnotatedMethodAttribute(
+	ConstUtf8 nameAttr, short version, short annFlags,
+	InsnTarget[] annRanges) {
+        super(nameAttr);
+        attrVersion = version;
+        annotationFlags = annFlags;
+        annotationRanges = annRanges;
+    }
+
+    /* package local methods */
+
+    static AnnotatedMethodAttribute read(
+	ConstUtf8 attrName, DataInputStream data, CodeEnv env)
+        throws IOException {
+        short version = data.readShort();
+        short annFlags = data.readShort();
+
+        short nRanges = data.readShort();
+
+        InsnTarget ranges[] = new InsnTarget[nRanges*2];
+        for (int i=0; i<nRanges; i++) {
+            ranges[i*2] = env.getTarget(data.readShort());
+            ranges[i*2+1] = env.getTarget(data.readShort());
+        }
+        return  new AnnotatedMethodAttribute(attrName, version, annFlags, ranges);
+    }
+
+    void write(DataOutputStream out) throws IOException {
+        out.writeShort(attrName().getIndex());
+        if (annotationRanges == null)
+            out.writeShort(2);
+        else
+            out.writeShort(4 + 2 * annotationRanges.length);
+        out.writeShort(attrVersion);
+        out.writeShort(annotationFlags);
+        if (annotationRanges == null)
+            out.writeShort(0);
+        else {
+            out.writeShort(annotationRanges.length / 2);
+            for (int i=0; i<annotationRanges.length; i++)
+                out.writeShort(annotationRanges[i].offset());
+        }
+    }
+
+    void print(PrintStream out, int indent) {
+        ClassPrint.spaces(out, indent);
+        out.println("version: " + attrVersion);
+        out.println(" flags: " + annotationFlags);
+        if (annotationRanges != null) {
+            out.println("Annotations: ");
+            for (int i=0; i<annotationRanges.length/2; i++) {
+                ClassPrint.spaces(out, indent+2);
+                out.println(annotationRanges[i*2] + " to " +
+                            annotationRanges[i*2+1]);
+            }
+        }
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AttributeVector.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AttributeVector.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AttributeVector.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/AttributeVector.java Sun May 22 10:55:51 2005
@@ -0,0 +1,213 @@
+/*
+ * 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.Vector;
+import java.util.Stack;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+/**
+ * A list of attributes within a class file.
+ * These lists occur in several places within a class file
+ *    - at class level
+ *    - at method level
+ *    - at field level
+ *    - at attribute level
+ */
+public class AttributeVector {
+
+    /* Vector of ClassAttribute */
+    private ClassAttribute attributes[] = null;
+
+    /**
+     * Returns the i'th attribute in the array
+     */
+    private ClassAttribute attrAt(int i) {
+        return attributes[i];
+    }
+
+    /**
+     * Construct an empty AttributeVector
+     */
+    public AttributeVector() { }
+
+    /**
+     * Add an element to the vector
+     */
+    public void addElement(ClassAttribute attr) {
+        if (attributes == null)
+            attributes = new ClassAttribute[1];
+        else {
+            ClassAttribute newAttributes[] = new ClassAttribute[attributes.length+1];
+            System.arraycopy(attributes, 0, newAttributes, 0, attributes.length);
+            attributes = newAttributes;
+        }
+        attributes[attributes.length-1] = attr;
+    }
+
+    public Enumeration elements() {
+        class AttributeVectorEnumeration implements Enumeration {
+            private ClassAttribute[] attributes;
+            private int current = 0;
+
+            AttributeVectorEnumeration(ClassAttribute attrs[]) {
+                attributes = attrs;
+            }
+
+            public boolean hasMoreElements() {
+                return attributes != null && current < attributes.length;
+            }
+            public Object nextElement() {
+                if (!hasMoreElements())
+                    throw new NoSuchElementException();
+                return attributes[current++];
+            }
+        }
+
+        return new AttributeVectorEnumeration(attributes);
+    }
+
+    /**
+     * Look for an attribute of a specific name
+     */
+    public ClassAttribute findAttribute(String attrName) {
+        Enumeration e = elements();
+        while (e.hasMoreElements()) {
+            ClassAttribute attr = (ClassAttribute) e.nextElement();
+            if (attr.attrName().asString().equals(attrName))
+                return attr;
+        }
+        return null;
+    }
+
+    /**
+     * Compares this instance with another for structural equality.
+     */
+    //@olsen: added method
+    public boolean isEqual(Stack msg, Object obj) {
+        if (!(obj instanceof AttributeVector)) {
+            msg.push("obj/obj.getClass() = "
+                     + (obj == null ? null : obj.getClass()));
+            msg.push("this.getClass() = "
+                     + this.getClass());
+            return false;
+        }
+        AttributeVector other = (AttributeVector)obj;
+
+        if (this.attributes.length != other.attributes.length) {
+            msg.push("attributes.length "
+                     + String.valueOf(other.attributes.length));
+            msg.push("attributes.length "
+                     + String.valueOf(this.attributes.length));
+            return false;
+        }
+
+        // sort attributes by name
+        class ClassAttributeComparator implements Comparator {
+            public int compare(Object o1, Object o2) {
+                ClassAttribute a1 = (ClassAttribute)o1;
+                ClassAttribute a2 = (ClassAttribute)o2;
+                String s1 = a1.attrName().asString();
+                String s2 = a2.attrName().asString();
+                return s1.compareTo(s2);
+            }
+        }
+        ClassAttributeComparator comparator = new ClassAttributeComparator();
+        ClassAttribute[] thisAttributes
+            = (ClassAttribute[])this.attributes.clone();
+        ClassAttribute[] otherAttributes
+            = (ClassAttribute[])other.attributes.clone();
+        Arrays.sort(thisAttributes, comparator);
+        Arrays.sort(otherAttributes, comparator);
+        for (int i = 0; i < attributes.length; i++) {
+            ClassAttribute a1 = thisAttributes[i];
+            ClassAttribute a2 = otherAttributes[i];
+            if (!a1.isEqual(msg, a2)) {
+                msg.push("attributes[i] = " + String.valueOf(a2));
+                msg.push("attributes[i] = " + String.valueOf(a1));
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * General attribute reader
+     */
+    static AttributeVector readAttributes(
+	DataInputStream data, ConstantPool constantPool)
+	throws IOException {
+        AttributeVector attribs = new AttributeVector();
+        int n_attrs = data.readUnsignedShort();
+        while (n_attrs-- > 0) {
+            attribs.addElement(ClassAttribute.read(data, constantPool));
+        }
+        return attribs;
+    }
+
+    /**
+     * ClassMethod attribute reader
+     */
+    static AttributeVector readAttributes(
+	DataInputStream data, CodeEnv codeEnv)
+	throws IOException {
+        AttributeVector attribs = new AttributeVector();
+        int n_attrs = data.readUnsignedShort();
+        while (n_attrs-- > 0) {
+            attribs.addElement(ClassAttribute.read(data, codeEnv));
+        }
+        return attribs;
+    }
+
+    /**
+     * Write the attributes to the output stream
+     */
+    void write(DataOutputStream out) throws IOException {
+        if (attributes == null) {
+            out.writeShort(0);
+        } else {
+            out.writeShort(attributes.length);
+            for (int i=0; i<attributes.length; i++)
+                attributes[i].write(out);
+        }
+    }
+
+    /**
+     * Print a description of the attributes
+     */
+    void print(PrintStream out, int indent) {
+        if (attributes != null) {
+            for (int i=0; i<attributes.length; i++)
+                attributes[i].print(out, indent);
+        }
+    }
+
+    /**
+     * Print a brief summary of the attributes
+     */
+    //@olsen: added 'out' and 'indent' parameters
+    void summarize(PrintStream out, int indent) {
+        ClassPrint.spaces(out, indent);
+        out.println((attributes == null ? 0 : attributes.length) +
+                           " attributes");
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassAttribute.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassAttribute.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassAttribute.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassAttribute.java Sun May 22 10:55:51 2005
@@ -0,0 +1,162 @@
+/*
+ * 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.Vector;
+import java.util.Hashtable;
+import java.io.*;
+
+/**
+ * An abstract base class for the attributes within a class file
+ */
+public abstract class ClassAttribute implements VMConstants {
+
+    /* The name of the attribute */
+    private ConstUtf8 attributeName;
+
+    /**
+     * Returns the name of the attribute
+     */
+    public ConstUtf8 attrName() {
+        return attributeName;
+    }
+
+    /**
+     * Compares this instance with another for structural equality.
+     */
+    //@olsen: added method
+    public boolean isEqual(Stack msg, Object obj) {
+        if (!(obj instanceof ClassAttribute)) {
+            msg.push("obj/obj.getClass() = "
+                     + (obj == null ? null : obj.getClass()));
+            msg.push("this.getClass() = "
+                     + this.getClass());
+            return false;
+        }
+        ClassAttribute other = (ClassAttribute)obj;
+
+        if (!this.attributeName.isEqual(msg, other.attributeName)) {
+            msg.push(String.valueOf("attributeName = "
+                                    + other.attributeName));
+            msg.push(String.valueOf("attributeName = "
+                                    + this.attributeName));
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Constructor
+     */
+    ClassAttribute(ConstUtf8 theAttrName) {
+        attributeName = theAttrName;
+    }
+
+    /**
+     * General attribute reader 
+     */
+    static ClassAttribute read(DataInputStream data, ConstantPool pool)
+	throws IOException {
+
+        ClassAttribute attr = null;
+        int attrNameIndex = data.readUnsignedShort();
+        ConstUtf8 attrName8 = (ConstUtf8) pool.constantAt(attrNameIndex);
+        String attrName = attrName8.asString();
+        int attrLength = data.readInt();
+
+        if (attrName.equals(CodeAttribute.expectedAttrName)) {
+            /* The old style code attribute reader uses more memory and
+               cpu when the instructions don't need to be examined than the
+               new deferred attribute reader.  We may at some point decide that
+               we want to change the default based on the current situation
+               but for now we will just use the deferred reader in all cases. */
+            if (true) {
+                attr = CodeAttribute.read(attrName8, attrLength, data, pool);
+            } else {
+                attr = CodeAttribute.read(attrName8, data, pool);
+            }
+        }
+        else if (attrName.equals(SourceFileAttribute.expectedAttrName)) {
+            attr = SourceFileAttribute.read(attrName8, data, pool);
+        }
+        else if (attrName.equals(ConstantValueAttribute.expectedAttrName)) {
+            attr = ConstantValueAttribute.read(attrName8, data, pool);
+        }
+        else if (attrName.equals(ExceptionsAttribute.expectedAttrName)) {
+            attr = ExceptionsAttribute.read(attrName8, data, pool);
+        }
+        else if (attrName.equals(AnnotatedClassAttribute.expectedAttrName)) {
+            attr = AnnotatedClassAttribute.read(attrName8, data, pool);
+        }
+        else {
+            /* Unrecognized method attribute */
+            byte attrBytes[] = new byte[attrLength];
+            data.readFully(attrBytes);
+            attr = new GenericAttribute (attrName8, attrBytes);
+        }
+
+        return attr;
+    }
+
+    /*
+     * CodeAttribute attribute reader
+     */
+
+    static ClassAttribute read(DataInputStream data, CodeEnv env)
+	throws IOException {
+        ClassAttribute attr = null;
+        int attrNameIndex = data.readUnsignedShort();
+        ConstUtf8 attrName8 = (ConstUtf8) env.pool().constantAt(attrNameIndex);
+        String attrName = attrName8.asString();
+        int attrLength = data.readInt();
+
+        if (attrName.equals(LineNumberTableAttribute.expectedAttrName)) {
+            attr = LineNumberTableAttribute.read(attrName8, data, env);
+        }
+        else if (attrName.equals(LocalVariableTableAttribute.expectedAttrName)) {
+            attr = LocalVariableTableAttribute.read(attrName8, data, env);
+        }
+        else if (attrName.equals(AnnotatedMethodAttribute.expectedAttrName)) {
+            attr = AnnotatedMethodAttribute.read(attrName8, data, env);
+        }
+        //@olsen: fix 4467428, added support for synthetic code attribute
+        else if (attrName.equals(SyntheticAttribute.expectedAttrName)) {
+            attr = SyntheticAttribute.read(attrName8, data, env.pool());
+        }
+        else {
+            /* Unrecognized method attribute */
+            byte attrBytes[] = new byte[attrLength];
+            data.readFully(attrBytes);
+            attr = new GenericAttribute (attrName8, attrBytes);
+        }
+
+        return attr;
+    }
+
+    /**
+     * Write the attribute to the output stream
+     */
+    abstract void write(DataOutputStream out) throws IOException;
+
+    /**
+     * Print a description of the attribute to the print stream
+     */
+    abstract void print(PrintStream out, int indent);
+}
+

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassField.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassField.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassField.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassField.java Sun May 22 10:55:51 2005
@@ -0,0 +1,142 @@
+/*
+ * 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.*;
+
+/**
+ * ClassField models the static and non-static fields of a class within
+ * a class file.
+ */
+
+final public class ClassField extends ClassMember {
+  /* access flag bit mask - see VMConstants */
+  private int accessFlags;
+
+  /* The name of the field */
+  private ConstUtf8 fieldName;
+
+  /* The type signature of the field */
+  private ConstUtf8 fieldSignature;
+
+  /* The attributes associated with the field */
+  private AttributeVector fieldAttributes;
+  
+
+  /* public accessors */
+
+  /**
+   * Is the field transient?
+   */
+  public boolean isTransient() {
+    return (accessFlags & ACCTransient) != 0;
+  }
+
+  /**
+   * Return the access flags for the field - see VMConstants
+   */
+  public int access() {
+    return accessFlags;
+  }
+
+  /**
+   * Update the access flags for the field - see VMConstants
+   */
+  public void setAccess(int newFlags) {
+    accessFlags = newFlags;
+  }
+
+  /**
+   * Return the name of the field
+   */
+  public ConstUtf8 name() {
+    return fieldName;
+  }
+
+  /**
+   * Change the name of the field
+   */
+  public void changeName(ConstUtf8 name) {
+    fieldName = name;
+  }
+
+  /**
+   * Return the type signature of the field
+   */
+  public ConstUtf8 signature() {
+    return fieldSignature;
+  }
+
+  /**
+   * Change the type signature of the field
+   */
+  public void changeSignature(ConstUtf8 newSig) {
+    fieldSignature = newSig;
+  }
+
+  /**
+   * Return the attributes associated with the field
+   */
+  public AttributeVector attributes() {
+    return fieldAttributes;
+  }
+
+  /**
+   * Construct a class field object
+   */
+  public ClassField(int accFlags, ConstUtf8 name, ConstUtf8 sig,
+                    AttributeVector field_attrs) {
+    accessFlags = accFlags;
+    fieldName = name;
+    fieldSignature = sig;
+    fieldAttributes = field_attrs;
+  }
+
+  /* package local methods */
+
+  static ClassField read(DataInputStream data, ConstantPool pool) 
+    throws IOException {
+    ClassField f = null;
+    int accessFlags = data.readUnsignedShort();
+    int name_index = data.readUnsignedShort();
+    int sig_index = data.readUnsignedShort();
+    AttributeVector fieldAttribs = AttributeVector.readAttributes(data, pool);
+    f = new ClassField(accessFlags, 
+		       (ConstUtf8) pool.constantAt(name_index),
+		       (ConstUtf8) pool.constantAt(sig_index),
+		       fieldAttribs);
+    return f;
+  }
+
+  void write (DataOutputStream data) throws IOException {
+    data.writeShort(accessFlags);
+    data.writeShort(fieldName.getIndex());
+    data.writeShort(fieldSignature.getIndex());
+    fieldAttributes.write(data);
+  }
+
+  void print(PrintStream out, int indent) {
+    ClassPrint.spaces(out, indent);
+    out.print("'" + fieldName.asString() + "'");
+    out.print(" sig = " + fieldSignature.asString());
+    out.print(" access_flags = " + Integer.toString(accessFlags));
+    out.println(" attributes:");
+    fieldAttributes.print(out, indent+2);
+  }
+}
+

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassFile.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassFile.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassFile.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassFile.java Sun May 22 10:55:51 2005
@@ -0,0 +1,676 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.io.*;
+import java.security.MessageDigest;
+import java.security.DigestOutputStream;
+import java.security.NoSuchAlgorithmException;
+import java.io.DataOutputStream;
+
+
+/**
+ * ClassFile models the structure of a class as represented within
+ * a class file.
+ */
+final public class ClassFile implements VMConstants, Serializable {
+
+    /* Class file constants */
+    public static final int magic = 0xcafebabe;
+    
+    /*@craig added more flexible version checking.
+     */
+    public static final short[] [] jdkMajorMinorVersions = new short[][] {
+        new short[] {45,3}, // jdk 1.1
+        new short[] {46,0}, // jdk 1.2
+        new short[] {47,0}, // jdk 1.3
+        new short[] {48,0}  // jdk 1.4
+    };
+    public static final List jdkVersions = 
+        convertMajorMinorVersions(jdkMajorMinorVersions);
+
+    public static final String supportedVersions = printSupportedVersions();
+    
+    private int majorVersion = 0;
+    private int minorVersion = 0;
+    
+    /* The constant pool for the class file */
+    private ConstantPool constantPool = new ConstantPool();
+
+    /* access flag bit mask - see VMConstants */
+    private int accessFlags = 0;
+
+    /* The name of the class */
+    private ConstClass thisClassName;
+
+    /* The name of the super class */
+    private ConstClass superClassName;
+
+    /* A list of the interfaces which the class implements
+     * The contents are ConstClass objects
+     */
+    private Vector classInterfaces = new Vector();
+
+    /* A list of the fields which the class contains
+     * The contents are ClassField objects
+     */
+    private Vector classFields = new Vector();
+
+    /* A list of the methods which the class defines
+     * The contents are ClassMethod objects
+     */
+    private Vector classMethods = new Vector();
+
+    /* A list of the attributes associated with the class */
+    private AttributeVector classAttributes = new AttributeVector();
+
+    /** Static methods 
+     * Added for major.minor compatibility checking
+     */
+    private static List convertMajorMinorVersions(short[][] majorMinor) {
+        int length = majorMinor.length;
+        List result = new ArrayList(length);
+        for (int i = 0; i < length; i++) {
+            result.add(new Integer(majorMinor[i][0] * 65536 + majorMinor[i][1]));
+        }
+        return result;
+    }
+    
+    private static boolean isSupportedVersion(short major, short minor) {
+        Integer version = new Integer(major*65536 + minor);
+        return jdkVersions.contains(version);
+    }
+    
+    public static final String printSupportedVersions() {
+        StringBuffer buf = new StringBuffer("{"); //NOI18N
+        int length = jdkMajorMinorVersions.length;
+        for (int i = 0; i < length; i++) {
+            int major = jdkMajorMinorVersions[i][0];
+            int minor = jdkMajorMinorVersions[i][1];
+            buf.append("{"); buf.append(major); buf.append(","); 
+            buf.append(minor); buf.append("}"); //NOI18N
+        }
+        buf.append("}"); //NOI18N
+        return buf.toString();
+    }
+
+    /* public accessors */
+
+
+
+    /**
+     * Return the constant pool for the class file
+     */
+    public ConstantPool pool() {
+        return constantPool;
+    }
+
+    /**
+     * Return the access flags for the class - see VMConstants
+     */
+    public int access() {
+        return accessFlags;
+    }
+
+    /**
+     * Is the class final?
+     */
+    final public boolean isFinal() {
+        return (accessFlags & ACCFinal) != 0;
+    }
+
+    /**
+     * Is the class an interface?
+     */
+    final public boolean isInterface() {
+        return (accessFlags & ACCInterface) != 0;
+    }
+
+    /**
+     * Is the class public?
+     */
+    final public boolean isPublic() {
+        return (accessFlags & ACCPublic) != 0;
+    }
+
+    /**
+     * Is the class abstract?
+     */
+    final public boolean isAbstract() {
+        return (accessFlags & ACCAbstract) != 0;
+    }
+
+
+    /**
+     * Set the access flags for the class - see VMConstants
+     */
+    public void setAccessFlags (int flags) {
+        accessFlags = flags;
+    }
+
+    /**
+     * Return the name of the class
+     */
+    public ConstClass className() {
+        return thisClassName;
+    }
+
+    /**
+     * Return the name of the class as a string
+     */
+    //@olsen: added method
+    public String classNameString() {
+        return (thisClassName == null) ? null : thisClassName.asString();
+    }
+
+    /**
+     * Return the name of the super class
+     */
+    public ConstClass superName() {
+        return superClassName;
+    }
+
+    /**
+     * Return the name of the super class as a string
+     */
+    public String superNameString() {
+        return (superClassName == null) ? null : superClassName.asString();
+    }
+
+    /**
+     * Set the name of the super class
+     */
+    public void setSuperName(ConstClass superCl) {
+        superClassName = superCl;
+    }
+
+    /**
+     * Return the list of the interfaces which the class implements
+     * The contents are ConstClass objects
+     */
+    public Vector interfaces() {
+        return classInterfaces;
+    }
+
+    /**
+     * Add an interface to the list of the interfaces which the class implements
+     */
+    public void addInterface (ConstClass iface) {
+        classInterfaces.addElement(iface);
+    }
+
+    /**
+     * Return the list of the fields which the class contains
+     * The contents are ClassField objects
+     */
+    public Vector fields() {
+        return classFields;
+    }
+
+    /**
+     * Add a field to the list of the fields which the class contains
+     */
+    public void addField (ClassField field) {
+        classFields.addElement(field);
+    }
+
+    /**
+     * Add a field to the list of the fields which the class contains,
+     * at the index'th position.
+     */
+    public void addField(ClassField field, int index) {
+        classFields.insertElementAt(field, index);
+    }
+
+    /**
+     * Return the list of the methods which the class defines
+     * The contents are ClassMethod objects
+     */
+    public Vector methods() {
+        return classMethods;
+    }
+
+    /**
+     * Look for a method with the specified name and type signature
+     */
+    public ClassMethod findMethod(String methodName, String methodSig) {
+        for (Enumeration e = methods().elements(); e.hasMoreElements();) {
+            ClassMethod method = (ClassMethod) e.nextElement();
+            if (method.name().asString().equals(methodName) &&
+                method.signature().asString().equals(methodSig))
+                return method;
+        }
+        return null;
+    }
+
+    /**
+     * Add a method to the list of the methods which the class defines
+     */
+    public void addMethod(ClassMethod method) {
+        classMethods.addElement(method);
+    }
+
+    /**
+     * Look for a field with the specified name
+     */
+    public ClassField findField(String fieldName) {
+        for (Enumeration e = fields().elements(); e.hasMoreElements();) {
+            ClassField field = (ClassField) e.nextElement();
+            if (field.name().asString().equals(fieldName))
+                return field;
+        }
+        return null;
+    }
+
+    /**
+     * Return the list of the attributes associated with the class
+     */
+    public AttributeVector attributes() {
+        return classAttributes;
+    }
+
+    /**
+     * Returns the class name in user ('.' delimited) form.
+     */
+    //@olsen: moved from ClassControl to ClassFile
+    public String userClassName()
+    {
+        return userClassFromVMClass(classNameString());
+    }
+  
+    /**
+     * Returns the class name in user ('.' delimited) form.
+     */
+    //@olsen: moved from ClassControl to ClassFile
+    static public String userClassFromVMClass(String vmName)
+    {
+        return vmName.replace('/', '.');
+    }
+  
+    /**
+     * Returns the class name in VM ('/' delimited) form.
+     */
+    //@olsen: moved from ClassControl to ClassFile
+    static public String vmClassFromUserClass(String userName)
+    {
+        return userName.replace('.', '/');
+    }
+  
+    /**
+     * Returns the vm package name for this class.
+     */
+    //@olsen: moved from ClassControl to ClassFile
+    public String pkg()
+    {
+        return packageOf(classNameString());
+    }
+  
+    /**
+     * Returns the vm package name for the vm class name.
+     */
+    //@olsen: moved from ClassControl to ClassFile
+    static public String packageOf(String vmName)
+    {
+        int last = vmName.lastIndexOf('/');
+        if (last < 0)
+            return "";
+        return vmName.substring(0, last);
+    }
+
+
+    /* Constructors */
+
+    /**
+     * Construct a ClassFile from an input stream
+     */
+    public ClassFile(DataInputStream data) throws ClassFormatError {
+        this(data, true);
+    }
+
+    public ClassFile(DataInputStream data,
+                     boolean allowJDK12ClassFiles) throws ClassFormatError {
+        try {
+            int thisMagic = data.readInt();
+            if (thisMagic != magic)
+                throw new ClassFormatError("Bad magic value for input");
+
+            short thisMinorVersion = data.readShort();
+            short thisMajorVersion = data.readShort();
+            /*@craig changed checking only target 1.1 and 1.2 to more
+             * general check for a list of versions.
+             */
+             if (isSupportedVersion(thisMajorVersion, thisMinorVersion)) {
+                minorVersion = thisMinorVersion;
+                majorVersion = thisMajorVersion;
+            } else {
+                throw new ClassFormatError("Bad version number: {" +
+                                           thisMajorVersion + "," + 
+                                           thisMinorVersion +
+                                           "} expected one of: " +
+                                           supportedVersions);
+            }
+
+            readConstants(data);
+            accessFlags = data.readUnsignedShort();
+            thisClassName = (ConstClass)
+                constantPool.constantAt(data.readUnsignedShort());
+            superClassName = (ConstClass)
+                constantPool.constantAt(data.readUnsignedShort());
+            readInterfaces(data);
+            readFields(data);
+            readMethods(data);
+            classAttributes = AttributeVector.readAttributes(data, constantPool);
+        } catch (IOException e) {
+            throw new ClassFormatError("IOException during reading: " + 
+                                       e.getMessage());
+        }
+        //@olsen: added println() for debugging
+        //System.out.println("ClassFile(): new class = " + 
+        //thisClassName.asString());
+    }
+
+    /**
+     * Construct a bare bones class, ready for additions
+     */
+    public ClassFile(String cname, String supername) {
+        thisClassName = constantPool.addClass(cname);
+        superClassName = constantPool.addClass(supername);
+        //@olsen: added println() for debugging
+        //System.out.println("ClassFile(): new bare class file = " + 
+        //thisClassName);
+    }
+
+    /**
+     * Write the Class file to the data output stream
+     */
+    public
+    void write (DataOutputStream buff) throws IOException {
+        buff.writeInt(magic);
+        buff.writeShort(minorVersion);
+        buff.writeShort(majorVersion);
+        constantPool.write(buff);
+        buff.writeShort(accessFlags);
+        buff.writeShort(thisClassName.getIndex());
+        //@lars: superclass may be null (java.lang.Object); 
+        //VMSpec 2nd ed., section 4.1
+        buff.writeShort(superClassName == null ? 0 : superClassName.getIndex());
+        //buff.writeShort(superClassName.getIndex());
+        writeInterfaces(buff);
+        writeFields(buff);
+        writeMethods(buff);
+        classAttributes.write(buff);
+    }
+
+    /**
+     * Returns a byte array representation of this class.
+     */
+    public byte[] getBytes() throws java.io.IOException {
+        /* Write the class bytes to a file, for debugging. */
+
+        String writeClassToDirectory =
+            System.getProperty("filter.writeClassToDirectory");
+        if (writeClassToDirectory != null) {
+            String filename = writeClassToDirectory + java.io.File.separator +
+                thisClassName.asString() + ".class";
+            System.err.println("Writing class to file " + filename);
+            DataOutputStream stream = new DataOutputStream(
+                new java.io.FileOutputStream(filename));
+            write(stream);
+            stream.close();
+        }
+
+        /* Get the class bytes and return them. */
+
+        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+        write(new DataOutputStream(byteStream));
+
+        return byteStream.toByteArray();
+    }
+
+    //@olsen: added method
+    public void print(PrintStream out) {
+        print(out, 0);
+    }
+    
+    //@olsen: added 'indent' parameter
+    public void print(PrintStream out, int indent) {
+        constantPool.print(out, indent);
+        out.println();
+
+        ClassPrint.spaces(out, indent);
+        out.println("majorVersion = " + Integer.toString(majorVersion));
+        ClassPrint.spaces(out, indent);
+        out.println("minorVersion = " + Integer.toString(minorVersion));
+        ClassPrint.spaces(out, indent);
+        out.println("accessFlags = " + Integer.toString(accessFlags));
+        ClassPrint.spaces(out, indent);
+        out.println("className = " + thisClassName.asString());
+        ClassPrint.spaces(out, indent);
+        out.println("superClassName = " + superClassName.asString());
+        ClassPrint.spaces(out, indent);
+        out.print("Interfaces =");
+        for (int i=0; i<classInterfaces.size(); i++) {
+            out.print(" "
+                      + ((ConstClass)classInterfaces.elementAt(i)).asString());
+        }
+        out.println();
+
+        ClassPrint.spaces(out, indent);
+        out.println("fields =");
+        for (int i=0; i<classFields.size(); i++) {
+            ((ClassField) classFields.elementAt(i)).print(out, indent + 3);
+        }
+
+        ClassPrint.spaces(out, indent);
+        out.println("methods =");
+        for (int i=0; i<classMethods.size(); i++) {
+            ((ClassMethod) classMethods.elementAt(i)).print(out, indent + 3);
+        }
+
+        ClassPrint.spaces(out, indent);
+        out.println("attributes =");
+        classAttributes.print(out, indent + 3);
+
+    }
+
+    //@olsen: made public
+    //@olsen: added 'out' and 'indent' parameters
+    public void summarize(PrintStream out, int indent) {
+        constantPool.summarize(out, indent);
+        int codeSize = 0;
+        for (int i=0; i<classMethods.size(); i++) {
+            codeSize += ((ClassMethod)classMethods.elementAt(i)).codeSize();
+        }
+        ClassPrint.spaces(out, indent);
+        out.println(classMethods.size() + " methods in "
+                    + codeSize + " bytes");
+        ClassPrint.spaces(out, indent);
+        out.println(classFields.size() + " fields");
+    }
+
+    /* package local methods */
+
+    /*
+     * class file reading helpers
+     */
+    private void readConstants (DataInputStream data) throws IOException {
+        constantPool = new ConstantPool(data);
+    }
+
+    private void readInterfaces(DataInputStream data) throws IOException {
+        int nInterfaces = data.readUnsignedShort();
+        while (nInterfaces-- > 0) {
+            int interfaceIndex = data.readUnsignedShort();
+            ConstClass ci = null;
+            if (interfaceIndex != 0)
+                ci = (ConstClass) constantPool.constantAt(interfaceIndex);
+            classInterfaces.addElement(ci);
+        }
+    }
+
+    private void writeInterfaces(DataOutputStream data) throws IOException {
+        data.writeShort(classInterfaces.size());
+        for (int i=0; i<classInterfaces.size(); i++) {
+            ConstClass ci = (ConstClass) classInterfaces.elementAt(i);
+            int interfaceIndex = 0;
+            if (ci != null)
+                interfaceIndex = ci.getIndex();
+            data.writeShort(interfaceIndex);
+        }
+    }
+
+    private void readFields(DataInputStream data) throws IOException {
+        int nFields = data.readUnsignedShort();
+        while (nFields-- > 0) {
+            classFields.addElement (ClassField.read(data, constantPool));
+        }
+    }
+
+    private void writeFields (DataOutputStream data) throws IOException {
+        data.writeShort(classFields.size());
+        for (int i=0; i<classFields.size(); i++)
+            ((ClassField)classFields.elementAt(i)).write(data);
+    }
+
+    private void readMethods (DataInputStream data) throws IOException {
+        int nMethods = data.readUnsignedShort();
+        while (nMethods-- > 0) {
+            classMethods.addElement (ClassMethod.read(data, constantPool));
+        }
+    }
+
+    private void writeMethods (DataOutputStream data) throws IOException {
+        data.writeShort(classMethods.size());
+        for (int i=0; i<classMethods.size(); i++)
+            ((ClassMethod)classMethods.elementAt(i)).write(data);
+    }
+
+}
+
+abstract class ArraySorter {
+    protected ArraySorter() {}
+
+    /* return the size of the array being sorted */
+    abstract int size();
+
+    /* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
+    abstract int compare(int o1Index, int o2Index);
+
+    /* Swap the elements at index o1Index and o2Index */
+    abstract void swap(int o1Index, int o2Index);
+
+    void sortArray() {
+        sortArray(0, size()-1);
+    }
+
+    private void sortArray(int start, int end) {
+        if (end > start) {
+            swap(start, (start+end)/2);
+            int last = start;
+            for (int i = start+1; i<=end; i++) {
+                if (compare(i, start) < 0)
+                    swap (++last, i);
+            }
+            swap(start, last);
+            sortArray(start, last-1);
+            sortArray(last+1, end);
+        }
+    }
+}
+
+class InterfaceArraySorter extends ArraySorter {
+    private ConstClass theArray[];
+
+    InterfaceArraySorter(ConstClass[] interfaces) {
+        theArray = interfaces;
+    }
+
+    /* return the size of the array being sorted */
+    int size() { return theArray.length; }
+
+    /* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
+    int compare(int o1Index, int o2Index) {
+        return theArray[o1Index].asString().compareTo(
+            theArray[o2Index].asString());
+    }
+
+    /* Swap the elements at index o1Index and o2Index */
+    void swap(int o1Index, int o2Index) {
+        ConstClass tmp = theArray[o1Index];
+        theArray[o1Index] = theArray[o2Index];
+        theArray[o2Index] = tmp;
+    }
+}
+
+class FieldArraySorter extends ArraySorter {
+    private ClassField theArray[];
+
+    FieldArraySorter(ClassField[] fields) {
+        theArray = fields;
+    }
+
+    /* return the size of the array being sorted */
+    int size() { return theArray.length; }
+
+    /* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
+    int compare(int o1Index, int o2Index) {
+        return theArray[o1Index].name().asString().compareTo(
+            theArray[o2Index].name().asString());
+    }
+
+    /* Swap the elements at index o1Index and o2Index */
+    void swap(int o1Index, int o2Index) {
+        ClassField tmp = theArray[o1Index];
+        theArray[o1Index] = theArray[o2Index];
+        theArray[o2Index] = tmp;
+    }
+}
+
+class MethodArraySorter extends ArraySorter {
+    private ClassMethod theArray[];
+
+    MethodArraySorter(ClassMethod[] methods) {
+        theArray = methods;
+    }
+
+    /* return the size of the array being sorted */
+    int size() { return theArray.length; }
+
+    /* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
+    int compare(int o1Index, int o2Index) {
+        int cmp = theArray[o1Index].name().asString().compareTo(
+            theArray[o2Index].name().asString());
+        if (cmp == 0) {
+            cmp = theArray[o1Index].signature().asString().compareTo(
+                theArray[o2Index].signature().asString());
+        }
+        return cmp;
+    }
+
+    /* Swap the elements at index o1Index and o2Index */
+    void swap(int o1Index, int o2Index) {
+        ClassMethod tmp = theArray[o1Index];
+        theArray[o1Index] = theArray[o2Index];
+        theArray[o2Index] = tmp;
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassMember.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassMember.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassMember.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/classfile/ClassMember.java Sun May 22 10:55:51 2005
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+/**
+ * ClassMember is a common base class for ClassMethod and ClassField
+ */
+abstract public class ClassMember implements VMConstants {
+
+    /* public accessors */
+
+    /**
+     * Is the member static?
+     */
+    final public boolean isStatic() {
+        return (access() & ACCStatic) != 0;
+    }
+
+    /**
+     * Is the member final?
+     */
+    final public boolean isFinal() {
+        return (access() & ACCFinal) != 0;
+    }
+
+    /**
+     * Turn on or off the final qualifier for the member.
+     */
+    public void setIsFinal(boolean newFinal) {
+        if (newFinal)
+            setAccess(access() | ACCFinal);
+        else
+            setAccess(access() & ~ACCFinal);
+    }
+
+    /**
+     * Is the member private?
+     */
+    final public boolean isPrivate() {
+        return (access() & ACCPrivate) != 0;
+    }
+
+    /**
+     * Is the member protected?
+     */
+    final public boolean isProtected() {
+        return (access() & ACCProtected) != 0;
+    }
+
+    /**
+     * Is the member public?
+     */
+    final public boolean isPublic() {
+        return (access() & ACCPublic) != 0;
+    }
+
+    /* These are expected to be implemented by subtypes */
+
+    /**
+     * Return the access flags for the method - see VMConstants
+     */
+    abstract public int access();
+
+    /**
+     * Set the access flags for the method - see VMConstants
+     */
+    abstract public void setAccess(int newAccess);
+
+    /**
+     * Return the name of the member
+     */
+    abstract public ConstUtf8 name();
+
+    /**
+     * Return the type signature of the method
+     */
+    abstract public ConstUtf8 signature();
+
+    /**
+     * Return the attributes associated with the member
+     */
+    abstract public AttributeVector attributes();
+
+    /**
+     * Compares this instance with another for structural equality.
+     */
+    //@olsen: added method
+    public boolean isEqual(Stack msg, Object obj) {
+        if (!(obj instanceof ClassMember)) {
+            msg.push("obj/obj.getClass() = "
+                     + (obj == null ? null : obj.getClass()));
+            msg.push("this.getClass() = "
+                     + this.getClass());
+            return false;
+        }
+        ClassMember other = (ClassMember)obj;
+
+        return true;
+    }
+}