db-jdo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m..@apache.org
Subject svn commit: r158176 [3/79] - in incubator/jdo/trunk/ri11: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/ejb/ 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/ src/java/org/apache/jdo/impl/fostore/ src/java/org/apache/jdo/impl/jdoql/ src/java/org/apache/jdo/impl/jdoql/jdoqlc/ src/java/org/apache/jdo/impl/jdoql/scope/ src/java/org/apache/jdo/impl/jdoql/tree/ src/java/org/apache/jdo/impl/model/ src/java/org/apache/jdo/impl/model/java/ src/java/org/apache/jdo/impl/model/java/runtime/ src/java/org/apache/jdo/impl/model/jdo/ src/java/org/apache/jdo/impl/model/jdo/caching/ src/java/org/apache/jdo/impl/model/jdo/util/ src/java/org/apache/jdo/impl/model/jdo/xml/ src/java/org/apache/jdo/impl/pm/ src/java/org/apache/jdo/impl/sco/ src/java/org/apache/jdo/impl/state/ src/java/org/apache/jdo/jdoql/ src/java/org/apache/jdo/jdoql/tree/ src/java/org/apache/jdo/model/ src/java/org/apache/jdo/model/java/ src/java/org/apache/jdo/model/jdo/ src/java/org/apache/jdo/pm/ src/java/org/apache/jdo/sco/ src/java/org/apache/jdo/state/ src/java/org/apache/jdo/store/ src/java/org/apache/jdo/util/ test/ test/conf/ test/enhancer/ test/enhancer/sempdept/ test/enhancer/sempdept/src/ test/enhancer/sempdept/src/empdept/ test/fsuid2/ test/fsuid2/org/ test/fsuid2/org/apache/ test/fsuid2/org/apache/jdo/ test/fsuid2/org/apache/jdo/pc/ test/java/ test/java/org/ test/java/org/apache/ test/java/org/apache/jdo/ test/java/org/apache/jdo/impl/ test/java/org/apache/jdo/impl/fostore/ test/java/org/apache/jdo/pc/ test/java/org/apache/jdo/pc/appid/ test/java/org/apache/jdo/pc/empdept/ test/java/org/apache/jdo/pc/serializable/ test/java/org/apache/jdo/pc/xempdept/ test/java/org/apache/jdo/test/ test/java/org/apache/jdo/test/query/ test/java/org/apache/jdo/test/util/ test/jdo/ test/jdo/org/ test/jdo/org/apache/ test/jdo/org/apache/jdo/ test/jdo/org/apache/jdo/pc/ test/jdo/org/apache/jdo/pc/appid/ test/jdo/org/apache/jdo/pc/empdept/ test/jdo/org/apache/jdo/pc/serializable/ test/jdo/org/apache/jdo/pc/xempdept/ xdocs/
Date Sat, 19 Mar 2005 01:05:57 GMT
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/Main.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/Main.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/Main.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/Main.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,957 @@
+/*
+ * 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.enhancer;
+
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.PrintWriter;
+import java.io.FileReader;
+import java.io.BufferedReader;
+
+import java.util.Map;
+import java.util.List;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import java.util.zip.ZipFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+import java.util.zip.ZipException;
+
+import java.net.URL;
+
+import org.apache.jdo.impl.enhancer.ClassFileEnhancer;
+import org.apache.jdo.impl.enhancer.ClassFileEnhancerHelper;
+import org.apache.jdo.impl.enhancer.ClassFileEnhancerTimer;
+import org.apache.jdo.impl.enhancer.EnhancerFatalError;
+import org.apache.jdo.impl.enhancer.EnhancerUserException;
+import org.apache.jdo.impl.enhancer.OutputStreamWrapper;
+import org.apache.jdo.impl.enhancer.core.EnhancerFilter;
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaData;
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataFatalError;
+import org.apache.jdo.impl.enhancer.meta.model.EnhancerMetaDataJDOModelImpl;
+import org.apache.jdo.impl.enhancer.meta.prop.EnhancerMetaDataPropertyImpl;
+import org.apache.jdo.impl.enhancer.meta.util.EnhancerMetaDataBaseModel;
+import org.apache.jdo.impl.enhancer.meta.util.EnhancerMetaDataTimer;
+import org.apache.jdo.impl.enhancer.util.CombinedResourceLocator;
+import org.apache.jdo.impl.enhancer.util.ListResourceLocator;
+import org.apache.jdo.impl.enhancer.util.PathResourceLocator;
+import org.apache.jdo.impl.enhancer.util.ResourceLocator;
+import org.apache.jdo.impl.enhancer.util.ResourceLocatorTimer;
+import org.apache.jdo.impl.enhancer.util.Support;
+
+
+
+
+
+/**
+ * Main is the starting point for the persistent filter tool.
+ */
+public class Main
+    extends Support
+{
+    // return values of main()
+    static public final int OK = 0;
+    static public final int USAGE_ERROR = -1;
+    static public final int METADATA_ERROR = -2;
+    static public final int CLASS_LOCATOR_ERROR = -3;
+    static public final int INTERNAL_ERROR = -4;
+
+    /**
+     *  The stream to write messages to.
+     */
+    private final PrintWriter out = new PrintWriter(System.out, true);
+
+    /**
+     *  The stream to write error messages to.
+     */
+    private final PrintWriter err = new PrintWriter(System.err, true);
+
+    /**
+     *  The command line options.
+     */
+    private final CmdLineOptions opts = new CmdLineOptions();
+
+    /**
+     *  The byte code enhancer.
+     */
+    private ClassFileEnhancer enhancer;
+
+    /**
+     *  The locator for classes.
+     */
+    protected ResourceLocator classLocator;
+
+    /**
+     *  The metadata for the enhancer.
+     */
+    private EnhancerMetaData jdoMetaData;
+
+    /**
+     * Construct a filter tool instance
+     */
+    public Main()
+    {}
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * This is where it all starts.
+     */
+    public static void main(String[] argv)
+    {
+        int res;
+        final Main main = new Main();
+
+        //@olsen: added support for timing statistics
+        try {
+            res = main.process(argv);
+        } catch (RuntimeException ex) {
+            main.out.flush();
+            main.err.println("Internal error while postprocessing: "
+                             + ex.getMessage());
+            ex.printStackTrace(main.err);
+            main.err.flush();
+            res = INTERNAL_ERROR;
+        } finally {
+            //@olsen: added support for timing statistics
+            if (main.opts.doTiming) {
+                Support.timer.print();
+            }
+        }
+        System.exit(res);
+    }
+
+    /**
+     * Process command line options and run enhancer.
+     */
+    public int process(String[] argv)
+    {
+        int res;
+
+        if ((res = opts.processArgs(argv)) != OK) {
+            printMessage("aborted with errors.");
+            return res;
+        }
+
+        //@olsen: added support for timing statistics
+        try {
+            if (opts.doTiming) {
+                timer.push("Main.process(String[])");
+            }
+
+            if ((res = createEnhancer()) != OK) {
+                printMessage("aborted with errors.");
+                return res;
+            }
+
+            if ((res = enhanceInputFiles(opts.classNames,
+                                         opts.classFileNames,
+                                         opts.zipFileNames,
+                                         opts.jdoFileNames)) != OK) {
+                printMessage("aborted with errors.");
+                return res;
+            }
+
+            printMessage("done.");
+            return 0;
+        } finally {
+            if (opts.doTiming) {
+                timer.pop();
+            }
+        }
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     *  A class for holding the command line options.
+     */
+    private class CmdLineOptions
+    {
+        final List classNames = new ArrayList();        
+        final List classFileNames = new ArrayList();        
+        final List zipFileNames = new ArrayList();        
+        final List jdoFileNames = new ArrayList();        
+        String sourcePath = null;
+        String destinationDirectory = null;
+        String propertiesFileName = null;
+        boolean doTiming = false;
+        boolean verbose = false;
+        boolean quiet = false;
+        boolean forceWrite = false;
+        boolean noWrite = false;
+        boolean dumpClass = false;
+        boolean noAugment = false;
+        boolean noAnnotate = false;
+
+        /**
+         * Print a usage message to System.err.
+         */
+        public void usage() {
+            err.println("Usage: main <options> <arguments>...");
+            err.println("Options:");
+            err.println("  -h, --help               print usage message and exit gently");
+            err.println("  -v, --verbose            print verbose messages");
+            err.println("  -q, --quiet              supress warnings");
+            err.println("  -s, --sourcepath <path>  source path for jdo and classfiles");
+            err.println("  -d, --destdir <dir>      destination directory for output files");
+            err.println("  -f, --force              overwrite output files");
+            err.println("  -n, --nowrite            never write output files");
+            err.println("  -t, --timing             do timing messures");
+            err.println();
+            err.println("Debugging Options:");
+            err.println("      --properties <file>  use property file for meta data");
+            err.println("      --dumpclass          print out disassembled code of classes");
+            err.println("      --noaugment          do not enhance for persistence-capability");
+            err.println("      --noannotate         do not enhance for persistence-awareness");
+            err.println();
+            err.println("Arguments:");
+            //err.println("  <class>      the fully qualified name of a Java class");
+            err.println("  <jdofile>    the name of a .jdo file");
+            err.println("  <classfile>  the name of a .class file");
+            //err.println("  <zipfile>    the name of a .zip or .jar file");
+            err.println();
+            err.println("Returns a non-zero value in case of errors.");
+        }
+
+        /**
+         * Process command line options.
+         */
+        protected int processArgs(String[] argv)
+        {
+            final Collection inputNames = new ArrayList();
+            for (int i = 0; i < argv.length; i++) {
+                final String arg = argv[i];
+                if (arg.equals("-h")
+                    || arg.equals("--help")) {
+                    usage();
+                    return OK;
+                }
+                if (arg.equals("-v")
+                    || arg.equals("--verbose")) {
+                    verbose = true;
+                    quiet = false;
+                    continue;
+                }
+                if (arg.equals("-q")
+                    || arg.equals("--quiet")) {
+                    quiet = true;
+                    verbose = false;
+                    continue;
+                }
+                if (arg.equals("-t") ||
+                    arg.equals("--timing")) {
+                    doTiming = true;
+                    continue;
+                }
+                if (arg.equals("-f")
+                    || arg.equals("--force")) {
+                    forceWrite = true;
+                    noWrite = false;
+                    continue;
+                }
+                if (arg.equals("-n")
+                    || arg.equals("--nowrite")) {
+                    noWrite = true;
+                    forceWrite = false;
+                    continue;
+                }
+                if (arg.equals("--dumpclass")) {
+                    dumpClass = true;
+                    continue;
+                }
+                if (arg.equals("--noaugment")) {
+                    noAugment = true;
+                    continue;
+                }
+                if (arg.equals("--noannotate")) {
+                    noAnnotate = true;
+                    continue;
+                }
+                if (arg.equals("-s")
+                    || arg.equals("--sourcepath")) {
+                    if (argv.length - i < 2) {
+                        printError("Missing argument to the -s/--sourcepath option", null);
+                        usage();
+                        return USAGE_ERROR;
+                    }
+                    sourcePath = argv[++i];
+                    continue;
+                }
+                if (arg.equals("-d")
+                    || arg.equals("--destdir")) {
+                    if (argv.length - i < 2) {
+                        printError("Missing argument to the -d/-destdir option", null);
+                        usage();
+                        return USAGE_ERROR;
+                    }
+                    destinationDirectory = argv[++i];
+                    continue;
+                }
+                if (arg.equals("--properties")) {
+                    if (argv.length - i < 2) {
+                        printError("Missing argument to the --properties option", null);
+                        usage();
+                        return USAGE_ERROR;
+                    }
+                    propertiesFileName = argv[++i];
+                    continue;
+                }
+                if (arg.length() > 0 && arg.charAt(0) == '-') {
+                    printError("Unrecognized option:" + arg, null);
+                    usage();
+                    return USAGE_ERROR;
+                }
+                if (arg.length() == 0) {
+                    printMessage("Ignoring empty command line argument.");
+                    continue;
+                }
+
+                inputNames.add(arg);
+            }
+
+            // group input file arguments
+            for (Iterator names = inputNames.iterator(); names.hasNext();) {
+                final String name = (String)names.next();
+                if (isJdoFileName(name)) {
+                    jdoFileNames.add(name);
+                } else if (isClassFileName(name)) {
+                    classFileNames.add(name);
+                } else if (isZipFileName(name)) {
+                    zipFileNames.add(name);
+                } else {
+                    classNames.add(name);
+                }
+            }
+
+            if (verbose) {
+                printArgs();
+            }
+            return checkArgs();
+        }
+
+        /**
+         * Check command line options.
+         */
+        protected int checkArgs()
+        {
+            // at least one class must be specified
+            if (classNames.isEmpty()
+                && classFileNames.isEmpty()
+                && zipFileNames.isEmpty()) {
+                final String msg
+                    = "No classes specified";
+                printError(msg, null);
+                usage();
+                return USAGE_ERROR;
+            }
+
+            // at least one meta-data source must be specified for classfiles
+            if (classFileNames.size() > 0
+                && (jdoFileNames.isEmpty()
+                    && propertiesFileName == null
+                    && sourcePath == null)) {
+                final String msg
+                    = "No JDO meta-data source specified for class files";
+                printError(msg, null);
+                usage();
+                return USAGE_ERROR;
+            }
+
+            // either jdo files or jdo properties specified
+            if (!jdoFileNames.isEmpty() && propertiesFileName != null) {
+                final String msg
+                    = "Cannot have both jdo files and properties specified";
+                printError(msg, null);
+                usage();
+                return USAGE_ERROR;
+            }
+
+            return OK;
+        }
+
+        /**
+         * Print command line options.
+         */
+        protected void printArgs()
+        {
+            out.println("Enhancer: options:");
+            out.println("    verbose = " + verbose);
+            out.println("    quiet = " + quiet);
+            out.println("    forceWrite = " + forceWrite);
+            out.println("    noWrite = " + noWrite);
+            out.println("    sourcePath = " + sourcePath);
+            out.println("    destinationDirectory = " + destinationDirectory);
+            out.println("    propertiesFileName = " + propertiesFileName);
+            out.println("    doTiming = " + doTiming);
+            out.println("    classNames = {");
+            for (Iterator i = classNames.iterator(); i.hasNext();) {
+                out.println("        " + i.next());
+            }
+            out.println("    }");
+            out.println("    jdoFileNames = {");
+            for (Iterator i = jdoFileNames.iterator(); i.hasNext();) {
+                out.println("        " + i.next());
+            }
+            out.println("    }");
+            out.println("    classFileNames = {");
+            for (Iterator i = classFileNames.iterator(); i.hasNext();) {
+                out.println("        " + i.next());
+            }
+            out.println("    }");
+            out.println("    zipFileNames = {");
+            for (Iterator i = zipFileNames.iterator(); i.hasNext();) {
+                out.println("        " + i.next());
+            }
+            out.println("    }");
+            out.println("    dumpClass = " + dumpClass);
+            out.println("    noAugment = " + noAugment);
+            out.println("    noAnnotate = " + noAnnotate);
+        }
+    }
+
+    private int initClassLocator()
+    {
+        final boolean verbose = opts.verbose;
+        final List classFileNames = opts.classFileNames;
+        final List zipFileNames = opts.zipFileNames;
+        final String sourcePath = opts.sourcePath;
+        try {
+            final List locators = new ArrayList();
+
+            // create resource locator for specified class files
+            if (classFileNames != null && !classFileNames.isEmpty()) {
+                final ResourceLocator classes
+                    = new ListResourceLocator(out, verbose, classFileNames);
+                if (verbose) {
+                    out.println("Class Locator: using class files: {");
+                    for (Iterator i = classFileNames.iterator(); i.hasNext();) {
+                        out.println("    " + i.next());
+                    }
+                    out.println("}");
+                }
+                locators.add(classes);
+            }
+
+            // create resource locator for specified zip files
+            if (zipFileNames != null && !zipFileNames.isEmpty()) {
+                final StringBuffer s = new StringBuffer();
+                final Iterator i = zipFileNames.iterator();
+                s.append(i.next());
+                while (i.hasNext()) {
+                    s.append(File.pathSeparator + i.next());
+                }
+                final ResourceLocator zips
+                    = new PathResourceLocator(out, verbose, s.toString());
+                if (verbose)
+                    out.println("Class Locator: using jar/zip files: "
+                                + s.toString());
+                locators.add(zips);
+            }
+
+            // create resource locator for specified source path
+            if (sourcePath != null && sourcePath.length() > 0) {
+                final ResourceLocator path
+                    = new PathResourceLocator(out, verbose, sourcePath);
+                if (verbose)
+                    out.println("Class Locator: using source path: "
+                                + sourcePath);
+                locators.add(path);
+            }
+
+            // print warning if no classes specified
+            affirm(!locators.isEmpty());
+            //if (locators.isEmpty()) {
+            //    printWarning(getI18N("enhancer.using_no_classes"));
+            //}
+
+            // init class locators
+            classLocator
+                = new CombinedResourceLocator(out, verbose, locators);
+
+            // wrap with timing class locator
+            if (opts.doTiming) {
+                classLocator = new ResourceLocatorTimer(classLocator);
+            }
+        } catch (IOException ex) {
+            printError("Cannot initialize resource locator for classes", ex);
+            return CLASS_LOCATOR_ERROR;
+        }
+        return OK;
+    }
+
+    private int initEnhancerMetaData()
+    {
+        final boolean verbose = opts.verbose;
+        final String propertiesFileName = opts.propertiesFileName;
+        final List jdoFileNames = opts.jdoFileNames;
+        final List zipFileNames = opts.zipFileNames;
+        final String sourcePath = opts.sourcePath;
+        try {
+            if (propertiesFileName != null) {
+                jdoMetaData
+                    = new EnhancerMetaDataPropertyImpl(out, verbose,
+                                                       propertiesFileName);
+            } else {
+                jdoMetaData
+                    = new EnhancerMetaDataJDOModelImpl(out, verbose,
+                                                       jdoFileNames,
+                                                       zipFileNames,
+                                                       sourcePath);
+            }
+
+            // wrap with timing meta data object
+            if (opts.doTiming) {
+                jdoMetaData = new EnhancerMetaDataTimer(jdoMetaData);
+            }
+        } catch (EnhancerMetaDataFatalError ex) {
+            printError("Cannot initialize JDO meta-data source", ex);
+            return METADATA_ERROR;
+        }
+        return OK;
+    }
+    
+    private int createEnhancer()
+    {
+        int res0 = initClassLocator();
+        if (res0 < 0) {
+            return res0;
+        }
+        affirm(classLocator != null);
+
+        int res = initEnhancerMetaData();
+        if (res < 0) {
+            return res;
+        }
+        affirm(jdoMetaData != null);
+
+        final Properties props = new Properties();
+        if (opts.verbose) {
+            props.put(EnhancerFilter.VERBOSE_LEVEL,
+                      EnhancerFilter.VERBOSE_LEVEL_VERBOSE);
+        }
+        
+        if (opts.doTiming) {
+            props.put(EnhancerFilter.DO_TIMING_STATISTICS,
+                      Boolean.TRUE.toString());
+        }
+
+        if (opts.dumpClass) {
+            props.put(EnhancerFilter.DUMP_CLASS,
+                      Boolean.TRUE.toString());
+        }
+
+        if (opts.noAugment) {
+            props.put(EnhancerFilter.NO_AUGMENT,
+                      Boolean.TRUE.toString());
+        }
+
+        if (opts.noAnnotate) {
+            props.put(EnhancerFilter.NO_ANNOTATE,
+                      Boolean.TRUE.toString());
+        }
+
+        try {            
+            enhancer = new EnhancerFilter(jdoMetaData, props, out, err);
+            if (opts.doTiming) {
+                // wrap with timing byte-code enhancer
+                enhancer = new ClassFileEnhancerTimer(enhancer);
+            }
+            return 0;
+        } catch (EnhancerUserException ex) {
+            printError("Error while creating the enhancer", ex);
+            return -1;
+        } catch (EnhancerFatalError ex) {
+            // enhancer is not anymore guaranteed to be consistent
+            printError("Fatal error while creating the enhancer", ex);
+            enhancer = null;
+            return -1;
+        }
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     *  Enhances all files entered in the command line.
+     *
+     *  @param  classNames  List of class names.
+     *  @param  classFileNames  List of class file names.
+     *  @param  zipFileNames  List of zip file names.
+     *  @param  jdoFileNames  List of jdo file names.
+     */
+    private int enhanceInputFiles(List classNames,
+                                  List classFileNames,
+                                  List zipFileNames,
+                                  List jdoFileNames)
+    {
+        int res = 0;
+        try {
+            String name = null;
+            for (Iterator i = zipFileNames.iterator(); i.hasNext();) {
+                try {
+                    name = (String)i.next();
+                    enhanceZipFile(name);
+                } catch (EnhancerUserException ex) {
+                    printError("Error while enhancing " + name, ex);
+                    res++;
+                    continue;
+                }
+            }
+            for (Iterator i = classFileNames.iterator(); i.hasNext();) {
+                try {
+                    name = (String)i.next();
+                    enhanceClassFile(openFileInputStream(name));
+                } catch (EnhancerUserException ex) {
+                    printError("Error while enhancing " + name, ex);
+                    res++;
+                    continue;
+                }
+            }
+            for (Iterator i = classNames.iterator(); i.hasNext();) {
+                try {
+                    name = (String)i.next();
+                    enhanceClassFile(openClassInputStream(name));
+                } catch (EnhancerUserException ex) {
+                    printError("Error while enhancing " + name, ex);
+                    res++;
+                    continue;
+                }
+            }
+        } catch (IOException ex) {
+            printError("IO Error while enhancing", ex);
+            return ++res;
+        } catch (EnhancerFatalError ex) {
+            // enhancer is not anymore guaranteed to be consistent
+            printError("Fatal error while enhancing", ex);
+            enhancer = null;
+            return ++res;
+        }
+        return res;
+    }
+
+    /**
+     *  Enhances a classfile.
+     *
+     *  @param  in  The input stream of the classfile.
+     */
+    private void enhanceClassFile(InputStream in)
+        throws IOException, EnhancerUserException, EnhancerFatalError
+    {
+        OutputStream out = null;
+        try {
+            final File temp = File.createTempFile("enhancer", ".class");
+            out = new BufferedOutputStream(new FileOutputStream(temp));
+
+            //enhance
+            final OutputStreamWrapper wrapper = new OutputStreamWrapper(out);
+            final boolean enhanced = enhancer.enhanceClassFile(in, wrapper);
+
+            closeOutputStream(out);
+            out = null;
+            createOutputFile(enhanced,
+                             createClassFileName(wrapper.getClassName()),
+                             temp);
+        } finally {
+            closeInputStream(in);
+            closeOutputStream(out);
+        }
+    }
+
+    /**
+     *  Enhances a zipfile.
+     *
+     *  @param  filename  The filename of the zipfile.
+     */
+    private void enhanceZipFile(String filename)
+        throws IOException, EnhancerUserException, EnhancerFatalError
+    {
+        ZipInputStream in = null;
+        ZipOutputStream out = null;
+        try {
+            final File temp = File.createTempFile("enhancer", ".zip");
+            in = new ZipInputStream(new BufferedInputStream(
+                new FileInputStream(new File(filename))));
+            out = new ZipOutputStream(new BufferedOutputStream(
+                new FileOutputStream(temp)));
+
+            //enhance the zipfile
+            final boolean enhanced
+                = ClassFileEnhancerHelper.enhanceZipFile(enhancer, in, out);
+
+            //create the output file
+            closeOutputStream(out);
+            out = null;
+            createOutputFile(enhanced, new File(filename).getName(), temp);
+        } finally {
+            closeOutputStream(out);
+            closeInputStream(in);
+        }
+    }
+
+    /**
+     *  Opens an input stream for the given filename
+     *
+     *  @param  filename  The name of the file.
+     *  @return  The input stream.
+     *  @exception  FileNotFoundException  If the file could not be found.
+     */
+    static private InputStream openFileInputStream(String filename)
+        throws FileNotFoundException
+    {
+     	return new BufferedInputStream(new FileInputStream(new File(filename)));
+    }
+
+    /**
+     * Opens an input stream for the given classname. The input stream is
+     * created via an URL that is obtained by the value of the sourcepath
+     * option and zip/jar file arguments.
+     * 
+     * @param  classname  The name of the class (dot-notation).
+     * @return  The input stream.
+     * @exception IOException If an I/O error occured.
+     */
+    private InputStream openClassInputStream(String classname)
+        throws IOException
+    {
+        final String resourcename = createClassFileName(classname);
+        return classLocator.getInputStreamForResource(resourcename);
+    }
+
+    /**
+     *  Creates a file object that represents the output zipfile for a given
+     *  zipfile to enhance.
+     *
+     *  @param  zipfilename  The input zipfile name.
+     *  @return  The output zipfile name.
+     */
+    private File createZipOutputFile(String zipfilename)
+    {
+        return new File(opts.destinationDirectory,
+                        new File(zipfilename).getName());
+    }
+
+    /**
+     *  Creates the output file for an enhaced class- or zipfile. If the
+     *  enhanced file is written back depends on the command line options.
+     *
+     *  @param  enhanced  Has the input file been enhanced?
+     *  @param  filename  The name of the output file.
+     *  @param  temp      The temp file, the output is written to.
+     *  @exception  IOException  If the file could not be created.
+     */
+    private void createOutputFile(boolean  enhanced,
+                                  String   filename,
+                                  File     temp)
+        throws IOException
+    {
+        //noWrite or (not enhanced and not forceWrite)
+        if (opts.noWrite || (!enhanced && !opts.forceWrite)) {
+            temp.deleteOnExit();
+            return;
+        }
+
+        File file = new File(opts.destinationDirectory, filename);
+        createPathOfFile(file);
+        file.delete();  //delete old file if exists
+        boolean renamed = temp.renameTo(file);
+        if (!renamed) {
+            //@dave: empirical evidence shows that renameTo does not allow for
+            // crossing filesystem boundaries.  If it fails, try "by hand".
+            InputStream in = null;
+            OutputStream out = null;
+            try {
+                in = new FileInputStream(temp);
+                out = new FileOutputStream(file);
+                int PAGESIZE = 4096; // Suggest a better size?
+                byte data[] = new byte[PAGESIZE];
+                while (in.available() > 0) {
+                    int numRead = in.read(data, 0, PAGESIZE);
+                    out.write(data, 0, numRead);
+                }
+                renamed = true;
+            } catch (IOException ex) {
+                throw new IOException("Could not rename temp file '" +
+                                      temp.getAbsolutePath() +
+                                      "' to '" + file.getAbsolutePath()
+                                      + "': " + ex);
+            } finally {
+                closeInputStream(in);
+                closeOutputStream(out);
+            }
+            if (renamed) {
+                temp.delete();  //delete temporary file
+            }
+            else {
+                throw new IOException("Could not rename temp file '" +
+                                      temp.getAbsolutePath() +
+                                      "' to '" + file.getAbsolutePath() + "'.");
+            }
+        }
+    }
+
+    /**
+     *  Closes an input stream.
+     *
+     *  @param  in  The input stream.
+     */
+    private void closeInputStream(InputStream in)
+    {
+        if (in != null) {
+            try {
+                in.close();
+            } catch (IOException ex) {
+                printError(null, ex);
+            }
+        }
+    }
+
+    /**
+     *  Closes an output stream.
+     *
+     *  @param  out  The output stream.
+     */
+    private void closeOutputStream(OutputStream out)
+    {
+        if (out != null) {
+            try {
+                out.close();
+            } catch (IOException ex) {
+                printError(null, ex);
+            }
+        }
+    }
+
+    /**
+     *  Tests if a filename is a classfile name (by testing if the filename
+     *  ends with <code>".class"</code>).
+     *
+     *  @param  filename  The name of the file.
+     *  @return  Do we have a potential classfile?
+     */
+    static private boolean isClassFileName(String filename)
+    {
+        return filename.toLowerCase().endsWith(".class");
+    }
+
+    /**
+     *  Tests if a filename is a zipfile (by testing if the filename
+     *  ends with <code>".zip"</code> or <code>".jar"</code>).
+     *
+     *  @param  filename  The name of the file.
+     */
+    static private boolean isZipFileName(String filename)
+    {
+        final int n = filename.length();
+        if (n < 5) {
+            return false;
+        }
+        final String ext = filename.substring(n - 4);
+        return ext.equalsIgnoreCase(".zip") || ext.equalsIgnoreCase(".jar");
+    }
+
+    /**
+     *  Tests if a filename is a jdo file name (by testing if the filename
+     *  ends with <code>".jdo"</code>).
+     *
+     *  @param  filename  The name of the file.
+     *  @return  Do we have a potential jdo file?
+     */
+    static private boolean isJdoFileName(String filename)
+    {
+        return filename.toLowerCase().endsWith(".jdo");
+    }
+
+    /**
+     *  Creates a filename from a classname.
+     *  This is done by replacing <code>'.'</code> by <code>'/'</code>.
+     *
+     *  @param  classname  The classname.
+     *  @return  The filename.
+     */
+    static private String createClassFileName(String classname)
+    {
+        return classname.replace('.', '/') + ".class";
+    }
+
+    /**
+     *  Creates only the path of the given file.
+     *
+     *  @param  file  The file.
+     *  @exception  IOException  If an error occured.
+     */
+    static private void createPathOfFile(File file)
+        throws IOException
+    {
+        File dir = file.getAbsoluteFile().getParentFile();
+        if (!dir.exists() && !dir.mkdirs()) {
+            throw new IOException("Error creating directory '"
+                                  + dir.getAbsolutePath() + "'.");
+        }
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     *  Prints out an error.
+     *
+     *  @param  msg  The error message (can be <code>null</code>).
+     *  @param  ex   An optional exception (can be <code>null</code>).
+     */
+    private void printError(String msg,
+                            Throwable ex)
+    {
+        out.flush();
+        if (msg != null) {
+            err.println(msg);
+        }
+        if (ex != null) {
+            if (opts.verbose) {
+                ex.printStackTrace(err);
+            }
+            else {
+                err.println(ex.toString());
+            }
+        }
+    }
+
+    /**
+     *  Prints out a message.
+     *
+     *  @param  msg  The message.
+     */
+    private void printMessage(String msg)
+    {
+        out.println(msg);
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/package.html
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/package.html?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/package.html (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/package.html Fri Mar 18 17:02:29 2005
@@ -0,0 +1,26 @@
+<!--
+ 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.
+-->
+
+<html>
+<head>
+<title>Package org.apache.jdo.enhancer</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
+</head>
+
+<body bgcolor="#FFFFFF">
+<p>This package contains th eenhancer interface.</p>
+</body>
+</html>

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Bundle.properties
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Bundle.properties?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Bundle.properties (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Bundle.properties Fri Mar 18 17:02:29 2005
@@ -0,0 +1,220 @@
+
+ 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.
+
+
+# ResourceBundle properties file for model messages
+# key consists of: enhancer.<subpackage>.<description>
+# <subpackage> - is optional, package under model
+# <description> - short description (use _ to represent space)
+# all keys should be in lowercase
+
+#
+# Global Enhancer Metadata messages
+#
+
+# {0}=detail message
+enhancer.metadata.message=JDO ENHANCER: Metadata: {0}
+
+# {0}=error message
+enhancer.metadata.error=JDO ENHANCER: Metadata Error: {0}
+
+# {0}=warning message
+enhancer.metadata.warning=JDO ENHANCER: Metadata Warning: {0}
+
+# {0}=missing resource file
+enhancer.metadata.cannot_read_resource=Cannot read directory or jar file: {0}
+
+#
+# Detail Enhancer Metadata messages
+#
+
+# {0}=exception message
+enhancer.metadata.jdomodel_error=A JDO model exception has occurred: {0}
+
+# {0}=exception message
+enhancer.metadata.io_error=An I/O exception has occurred: {0}
+
+# {0}=filename
+enhancer.metadata.using_properties=using properties file: {0}
+
+# {0}=filenames
+enhancer.metadata.using_jdo_files=using jdo files: {0}
+
+# {0}=path
+enhancer.metadata.using_jar_files=using jar/zip files: {0}
+
+# {0}=path
+enhancer.metadata.using_source_path=using source path: {0}
+
+# {0}=
+enhancer.metadata.using_no_metadata=no JDO metadata source was specified
+
+
+#
+# Global enhancer messages
+#
+
+# {0}=detailed message
+enhancer.message=JDO ENHANCER: {0}
+
+# {0}=detailed message
+enhancer.error=JDO ENHANCER: At least one error occurred while enhancing input class for Transparent Persistence; detailed message(s): {0}
+
+# {0}=error number, {1}=detailed message
+enhancer.enumerated_error=JDO ENHANCER: Error ({0}): {1}
+
+# {0}=detailed message
+enhancer.internal_error=JDO ENHANCER: An internal error occurred while enhancing input class; detailed message: {0}
+
+# {0}=detailed message
+enhancer.warning=JDO ENHANCER: Warning: {0}
+
+#
+# Enhancer core messages
+#
+
+#
+enhancer.class_format_error=I/O error while reading input stream or input stream does not denote a valid Java class.
+
+#
+enhancer.io_error_while_writing_stream=I/O error while writing output stream.
+
+# {0}=dir name
+enhancer.unable_to_create_dir=Unable to create the directory named {0}.
+
+# {0}=class name
+enhancer.class_previously_annotated=The class {0} was previously annotated.
+
+# {0}=boolean
+enhancer.class_implements_jdo_pc=implements the JDO PersistenceCapable interface: {0}.
+
+#
+enhancer.class_has_default_constructor=has default constructor.
+enhancer.class_has_not_default_constructor=has not default constructor.
+
+#
+enhancer.class_has_static_initializer=has static initializer.
+enhancer.class_has_not_static_initializer=has not static initializer.
+
+#
+enhancer.class_has_clone_method=has clone method.
+enhancer.class_has_not_clone_method=has not clone method.
+
+#
+enhancer.class_has_writeObject_method=has writeObject method.
+enhancer.class_has_not_writeObject_method=has not writeObject method.
+
+#
+enhancer.class_has_writeReplace_method=has writeReplace method.
+enhancer.class_has_not_writeReplace_method=has not writeReplace method.
+
+#
+enhancer.class_has_readObject_method=has readObject method.
+enhancer.class_has_not_readObject_method=has not readObject method.
+
+# {0}=class name
+enhancer.class_missing_default_constructor=The persistence-capable class {0} does not provide a default (no-argument) constructor.
+
+# {0}=boolean
+enhancer.class_has_generic_jdo_fields=has the generic JDO fields: {0}.
+
+# {0}=boolean
+enhancer.class_has_generic_jdo_methods=has the generic JDO methods: {0}.
+
+# {0}=boolean
+enhancer.class_has_generic_jdo_members=has the generic JDO fields and methods: {0}.
+
+# {0}=boolean
+enhancer.class_has_specific_jdo_fields=has the specific JDO fields: {0}.
+
+# {0}=boolean
+enhancer.class_has_specific_jdo_methods=has the specific JDO methods: {0}.
+
+# {0}=boolean
+enhancer.class_has_specific_jdo_members=has the specific JDO fields and methods: {0}.
+
+# {0}=boolean
+enhancer.class_has_oid_handling_jdo_methods=has the ObjectId-handling JDO methods: {0}.
+
+# {0}=boolean
+enhancer.class_has_callback_jdo_methods=has the instance-callback JDO methods: {0}.
+
+# {0}=class name, {1}=method name
+enhancer.class_defines_jdo_method=The persistence-capable class {0} defines a JDO method called {1}.
+
+# {0}=class name, {1}=field name
+enhancer.class_defines_jdo_field=The persistence-capable class {0} defines a JDO field called {1}.
+
+# {0}=class name, {1}=member name
+enhancer.class_has_jdo_like_member=The persistence-capable class {0} defines a member {1} whose name starts with the reserved jdo prefix.
+
+# {0}=class name, {1}=method name,
+# {2}=expected signature, {3}=found signature
+# {4}=expected modifiers, {5}=found modifiers
+enhancer.class_has_illegally_declared_jdo_member=The persistence-capable class {0} has an illegally declared JDO member: {1}; expected signature: ''{2}''; found signature: ''{3}''; expected access modifier flags: {4}; found access modifier flags: {5}.
+
+# {0}=class name, {1}=found method names, {2}=missing method names
+enhancer.class_has_inconsistently_declared_jdo_members=The persistence-capable class {0} has an incosistent set of declared JDO members; found: {1}; missing: {2}.
+
+#
+# Other Enhancer messages
+#
+
+# {0}=filenames
+enhancer.using_jdo_files=using jdo files: {0}
+
+# {0}=path
+enhancer.using_archive_files=using jar/zip files: {0}
+
+# {0}=path
+enhancer.using_source_path=using source path: {0}
+
+# {0}=resource file name
+enhancer.using_file=using file: {0}
+
+# {0}=resource path element
+enhancer.using_path_element=using path element: {0}
+
+# {0}=class name, {1}=file name, {2}=file name
+enhancer.class_already_entered=The class {0} from {1} is already entered from {2}.
+
+# {0}=dir name, {1}=dir name
+enhancer.destination_directory_already_set=Attempt to set the destination directory to {0}, but it has already been set to {1}.
+
+# {0}=dir name
+enhancer.destination_directory_not_exist=The destination directory {0} does not exist.
+
+# {0}=resource name
+enhancer.found_resource=found resource: {0}
+enhancer.not_found_resource=not found resource: {0}
+
+# {0}=resource name
+enhancer.cannot_read_resource=resource does not exist or cannot be read: {0}
+
+# {0}=resource name {1}=exception message
+enhancer.io_error_while_reading_resource=An I/O exception has occurred while reading resource: {0}, exception: {1}
+
+# {0}=resource name
+enhancer.io_error_while_reading_resource=An I/O exception has occurred: {0}
+
+# {0}=resource name
+enhancer.illegal_path_element=illegal element source path: {0}
+
+#
+# Enhancer exception messages
+#
+
+MSG_CauseThrowable=CauseThrowable:
+MSG_CauseThrowableStackTrace=CauseThrowableStackTrace:

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArgMain.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArgMain.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArgMain.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArgMain.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,180 @@
+/*
+ * 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.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+import java.io.File;
+
+import org.apache.jdo.impl.enhancer.util.PathResourceLocator;
+
+
+
+/**
+ * Base class for JDO command line enhancer and tests.
+ *
+ * @author Martin Zaun
+ */
+public class ClassArgMain
+    extends GenericMain
+{
+    /**
+     *  The options and arguments.
+     */
+    protected ClassArgOptions options;
+
+    /**
+     *  The locator for classes.
+     */
+    protected PathResourceLocator classes;
+
+    /**
+     * Creates an instance.
+     */
+    public ClassArgMain(PrintWriter out,
+                        PrintWriter err)
+    {
+        this(out, err, new ClassArgOptions(out, err));
+    }
+
+    /**
+     * Creates an instance.
+     */
+    public ClassArgMain(PrintWriter out,
+                        PrintWriter err,
+                        ClassArgOptions options)
+    {
+        super(out, err, options);
+        this.options = options;
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Initializes the class locator.
+     */
+    protected void initClassLocator()
+        throws IOException
+    {
+        // create resource locator for specified source path
+        final String path = options.sourcePath.value;
+        if (path != null) {
+            affirm(path.length() > 0);
+            final boolean verbose = options.verbose.value;
+            classes = new PathResourceLocator(out, verbose, path);
+        }
+    }
+
+    /**
+     * Initializes all components.
+     */
+    protected void init()
+        throws EnhancerFatalError, EnhancerUserException
+    {
+        try {
+            initClassLocator();
+        } catch (Exception ex) {
+            throw new EnhancerFatalError(ex);
+        }
+    }
+    
+    // ----------------------------------------------------------------------
+
+    /**
+     *  Returns the file name for a class name.
+     *  This is done by replacing <code>'.'</code> by <code>'/'</code>.
+     *
+     *  @param  className  the classname
+     *  @return  the filename
+     */
+    static protected String getClassFileName(String className)
+    {
+        return className.replace('.', '/') + ".class";
+    }
+
+    /**
+     *  Opens an input stream for the given filename
+     *
+     *  @param  fileName  the name of the file
+     *  @return  the input stream
+     *  @exception  FileNotFoundException  if the file could not be found
+     */
+    protected InputStream openFileInputStream(String fileName)
+        throws FileNotFoundException
+    {
+        affirm(fileName != null);
+        //^olsen: support for timing
+        //if (options.doTiming.value) {...}
+     	return new BufferedInputStream(new FileInputStream(fileName));
+    }
+
+    /**
+     * Opens an input stream for the given classname. The input stream is
+     * created via an URL that is obtained by the value of the sourcepath
+     * option and zip/jar file arguments.
+     * 
+     * @param  className  the name of the class (dot-notation)
+     * @return  the input stream
+     * @exception IOException if an I/O error occured
+     */
+    protected InputStream openClassInputStream(String className)
+        throws IOException
+    {
+        affirm(className != null);
+        final String resName = className.replace('.', '/') + ".class";
+        //^olsen: support for timing
+        //if (options.doTiming.value) {...}
+        final InputStream s = classes.getInputStreamForResource(resName);
+        affirm(s != null);
+        return new BufferedInputStream(s);
+    }
+
+    /**
+     *  Closes an input stream.
+     *
+     *  @param  in  the input stream
+     */
+    protected void closeInputStream(InputStream in)
+    {
+        if (in != null) {
+            try {
+                in.close();
+            } catch (IOException ex) {
+                printlnErr("", ex);
+            }
+        }
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Runs this class
+     */
+    static public void main(String[] args)
+    {
+        final PrintWriter out = new PrintWriter(System.out, true);
+        out.println("--> ClassArgMain.main()");
+        final ClassArgMain main = new ClassArgMain(out, out);
+        int res = main.run(args);
+        out.println("<-- ClassArgMain.main(): exit = " + res);
+        System.exit(res);
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArgOptions.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArgOptions.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArgOptions.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArgOptions.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,220 @@
+/*
+ * 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.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+
+/**
+ * Set of options used by the JDO enhancer and its test programs.
+ *
+ * @author Martin Zaun
+ */
+public class ClassArgOptions
+    extends GenericOptions
+{
+    /**
+     * Tests if a filename has suffix <code>".class"</code> (ignoring case).
+     *
+     * @param  filename  the name of the file
+     * @return true if filename has a class file suffix
+     */
+    static private boolean isClassFileName(String filename)
+    {
+        return filename.toLowerCase().endsWith(".class");
+    }
+
+    /**
+     * Tests if a filename has suffix <code>".jar"</code> or
+     * <code>".zip"</code> (ignoring case).
+     *
+     * @param  filename  the name of the file
+     * @return true if filename has an archive file suffix
+     */
+    static private boolean isArchiveFileName(String filename)
+    {
+        final String s = filename.toLowerCase();
+        return (s.endsWith(".jar") || s.endsWith(".zip"));
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * The source path option.
+     */
+    public final StringOption sourcePath
+        = createStringOption("sourcepath", "s",
+                             "<path>  : path for lookup of class files");
+
+    /**
+     * The list of class name arguments.
+     */
+    public final List classNames = new ArrayList();        
+
+    /**
+     * The list of class file name arguments.
+     */
+    public final List classFileNames = new ArrayList();        
+
+    /**
+     * The list of archive file name arguments.
+     */
+    public final List archiveFileNames = new ArrayList();        
+
+    /**
+     * Creates an instance.
+     */
+    public ClassArgOptions(PrintWriter out,
+                       PrintWriter err) 
+    {
+        super(out, err);
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printUsageHeader()
+    {
+        printlnErr("Usage: <options>.. <arguments>..");
+        printlnErr(indent
+                   + "-s <path>   <classname>..");
+        printlnErr(indent
+                   + "            <classfile>..");
+        //^olsen: re-enable support for archive files
+        //printlnErr(indent
+        //           + "            <archivefile>..");
+    }
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printArgumentUsage()
+    {
+        printlnErr(indent
+                   + "<classname>       the fully qualified name of a Java class");
+        printlnErr(indent
+                   + "<classfile>       the name of a .class file");
+        printlnErr(indent
+                   + "<archivefile>     the name of a .zip or .jar file");
+    }
+
+    /**
+     * Print arguments.
+     */
+    public void printArguments()
+    {
+        println();
+        println(argumentsHeader);
+        printListArgument("classNames", classNames);
+        printListArgument("classFileNames", classFileNames);
+        printListArgument("archiveFileNames", archiveFileNames);
+    }
+    
+    /**
+     * Print argument of list type.
+     */
+    public void printListArgument(String name, List list)
+    {
+        print(indent);
+        final StringBuffer s = new StringBuffer();
+        for (Iterator i = list.iterator(); i.hasNext();) {
+            s.append(" " + i.next());
+        }
+        println(name + " = {" + s.toString() + " }");
+        println();
+    }
+
+    /**
+     * Check options and arguments.
+     */
+    public int check()
+    {
+        int res;
+        if ((res = super.check()) != OK) {
+            return res;
+        }
+
+        // group input file arguments
+        for (Iterator names = arguments.iterator(); names.hasNext();) {
+            final String name = (String)names.next();
+            if (isClassFileName(name)) {
+                classFileNames.add(name);
+            } else if (isArchiveFileName(name)) {
+                archiveFileNames.add(name);
+            } else {
+                classNames.add(name);
+            }
+        }
+
+        if (verbose.value) {
+            printAll();
+        }
+        
+        // check class arguments
+        final int argTypes = ((classNames.isEmpty() ? 0 : 1)
+                              + (classFileNames.isEmpty() ? 0 : 1)
+                              + (archiveFileNames.isEmpty() ? 0 : 1));
+        if (argTypes == 0) {
+            printUsageError("No class arguments: specify classes either by class name, class file, or archive file");
+            return USAGE_ERROR;
+        }
+        if (argTypes > 1) {
+            printUsageError("Mixed class arguments: specify classes by either class name, class file, or archive file");
+            return USAGE_ERROR;
+        }
+        
+        // check sourcepath option
+        if (sourcePath.value == null && !classNames.isEmpty()) {
+            printUsageError("No source-path specified for lookup of classes");
+            return USAGE_ERROR;
+        }
+        if (sourcePath.value != null && classNames.isEmpty()) {
+            printUsageError("No source-path can be specified with class or archive files");
+            return USAGE_ERROR;
+        }
+
+        //^olsen: re-enable support for archive files
+        if (!archiveFileNames.isEmpty()) {
+            printUsageError("Sorry, support for archive files currently disabled");
+            return USAGE_ERROR;
+        }
+
+        return OK;
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Tests the class.
+     */
+    static public void main(String[] args)
+    {
+        final PrintWriter out = new PrintWriter(System.out, true);
+        out.println("--> ClassArgOptions.main()");
+        final ClassArgOptions options = new ClassArgOptions(out, out);
+        out.println("    options.process() ...");
+        int res = options.process(args);
+        out.println("    return value: " + res);
+        out.println("<-- ClassArgOptions.main()");
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancer.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancer.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancer.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancer.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,65 @@
+/*
+ * 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.InputStream;
+import java.io.OutputStream;
+
+/**
+ * A JDO enhancer, or byte-code enhancer, modifies the byte-codes of
+ * Java class files to enable transparent loading and storing of the
+ * fields of the persistent instances.
+ *
+ * @author Martin Zaun
+ */
+public interface ClassFileEnhancer
+{
+    /**
+     * Enhances a given class according to the JDO meta-data. If the
+     * input class has been enhanced or not - the output stream is
+     * always written, either with the enhanced class or with the
+     * non-enhanced class.
+     *
+     * @param in The byte-code of the class to be enhanced.
+     * @param out The byte-code of the enhanced class.
+     * @return  <code>true</code> if the class has been enhanced,
+     *          <code>false</code> otherwise.
+     */
+   boolean enhanceClassFile(InputStream in,
+                            OutputStream out)
+        throws EnhancerUserException, EnhancerFatalError;
+
+
+    /**
+     * Enhances a given class according to the JDO meta-data. If the
+     * input class has been enhanced or not - the output stream is
+     * always written, either with the enhanced class or with the
+     * non-enhanced class.
+     * <p>
+     * Furthermore, the enhancer has to set the classname of
+     * the enhanced class to the output stream wrapper object (it's
+     * possible to get the input stream without knowing the classname).
+     *
+     * @param in  The byte-code of the class to be enhanced.
+     * @param out The byte-code of the enhanced class.
+     * @return  <code>true</code> if the class has been enhanced,
+     *          <code>false</code> otherwise.
+     */
+    boolean enhanceClassFile(InputStream in,
+                             OutputStreamWrapper out)
+            throws EnhancerUserException, EnhancerFatalError;
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerHelper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerHelper.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerHelper.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerHelper.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,204 @@
+/*
+ * 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.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+
+/**
+ *  This is a helper-class to perform some useful operations outside a
+ *  byte code enhancer and delegate the real work to the enhancer.
+ */
+public class ClassFileEnhancerHelper
+{
+    /**
+     *  Enhances a classfile.
+     *
+     *  @param  enhancer  The enhancer to delegate the work to.
+     *  @param  in        The input stream with the Java class.
+     *  @param  out       The output stream to write the enhanced class to.
+     *
+     *  @return  Has the input stream been enhanced?
+     *
+     *  @exception  EnhancerUserException  If something went wrong.
+     *  @exception  EnhancerFatalError     If something went wrong.
+     *
+     *  @see  ClassFileEnhancer#enhanceClassFile
+     */
+    static public boolean enhanceClassFile(ClassFileEnhancer enhancer,
+                                           InputStream      in,
+                                           OutputStream     out)
+        throws EnhancerUserException,
+        EnhancerFatalError
+    {
+        return enhancer.enhanceClassFile(in, new OutputStreamWrapper(out));
+    }
+
+    /**
+     *  Enhances a zip file. The zip file is given as a uip input stream.
+     *  It's entries are read and - if necessary - individually enhanced.
+     *  The output stream has the same compressíon (if any) as the input
+     *  stream.
+     *
+     *  @param  enhancer  The enhancer.
+     *  @param  zip_in    The zip input stream.
+     *  @param  zip_out   The zip output stream.
+     *
+     *  @return  <code>true</code> if at least one entry of the zip file has
+     *           been enhanced, <code>false</code> otherwise.
+     *
+     *  @exception  EnhancerUserException  If something went wrong.
+     *  @exception  EnhancerFatalError     If something went wrong.
+     *
+     *  @see  ClassFileEnhancer#enhanceClassFile
+     */
+    static public boolean enhanceZipFile(ClassFileEnhancer enhancer,
+                                         ZipInputStream zip_in,
+                                         ZipOutputStream zip_out)
+        throws EnhancerUserException,
+        EnhancerFatalError
+    {
+        boolean enhanced = false;
+        try {
+            CRC32 crc32 = new CRC32();
+            ZipEntry entry;
+            while ((entry = zip_in.getNextEntry()) != null) {
+                InputStream in = zip_in;
+                final ZipEntry out_entry = new ZipEntry(entry);
+
+                // try to enhance
+                if (isClassFileEntry(entry)) {
+                    // enhance the classfile
+                    // we have to copy the classfile, because if it won't be
+                    // enhanced, the OutputStream is empty and we have to
+                    // re-read the InputStream, which is impossible with a
+                    // ZipInputStream (no mark/reset)
+                    in = openZipEntry(zip_in);
+                    in.mark(Integer.MAX_VALUE);
+                    final ByteArrayOutputStream tmp
+                        = new ByteArrayOutputStream();
+                    if (enhancer.enhanceClassFile(in, tmp)) {
+                        enhanced = true;
+                        final byte[] bytes = tmp.toByteArray();
+                        tmp.close();
+                        in.close();
+                        modifyZipEntry(out_entry, bytes, crc32);
+                        in = new ByteArrayInputStream(bytes);
+                    } else {
+                        // the classfile has not been enhanced
+                        in.reset();
+                    }
+                }
+
+                // copy the entry
+                zip_out.putNextEntry(out_entry);
+                copyZipEntry(in, zip_out);
+                zip_out.closeEntry();
+
+                if (in != zip_in) {
+                    in.close();
+                }
+            }
+        } catch (IOException ex) {
+            throw new EnhancerFatalError(ex);
+        }
+
+        return enhanced;
+    }
+
+    /**
+     *  Copies a zip entry from one stream to another.
+     *
+     *  @param  in   The inout stream.
+     *  @param  out  The output stream.
+     *
+     *  @exception  IOException  If the stream access failed.
+     */
+    static private void copyZipEntry(InputStream  in,
+                                     OutputStream out)
+        throws IOException
+    {
+        int b;
+        while ((in.available() > 0) && (b = in.read()) > -1) {
+            out.write(b);
+        }
+    }
+
+    /**
+     *  Opens the next zip entry of a zip input stream and copies it to
+     *  a <code>java.io.ByteArrayOutputStream</code>. It's byte array is made
+     *  available via an <code>java.io.ByteArrayInputStream</code> which is
+     *  returned.
+     *
+     *  @param  in  The zip input stream.
+     *
+     *  @return  The newly created input stream with the next zip entry.
+     *
+     *  @exception  IOException  If an I/O operation failed.
+     */
+    static private InputStream openZipEntry(ZipInputStream in)
+        throws IOException
+    {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        copyZipEntry(in, out);
+
+        return new ByteArrayInputStream(out.toByteArray());
+    }
+
+    /**
+     *  Modifies the given zip entry so that it can be added to zip file.
+     *  The given zip entry represents an enhanced class, so the zip entry
+     *  has to get the correct size and checksum (but only if the entry won't
+     *  be compressed).
+     *
+     *  @param  entry  The zip entry to modify.
+     *  @param  bytes  The uncompressed byte representation of the classfile.
+     *  @param  crc32  The checksum evaluator.
+     */
+    private static void modifyZipEntry(ZipEntry entry,
+                                       byte []  bytes,
+                                       CRC32    crc32)
+    {
+        entry.setSize(bytes.length);
+        if (entry.getMethod() == 0) {
+            //no compression (ZipInputStream.STORED - not accessible)
+            crc32.reset();
+            crc32.update(bytes);
+            entry.setCrc(crc32.getValue());
+            entry.setCompressedSize(bytes.length);
+        }
+    }
+
+    /**
+     *  Determines if a given entry represents a classfile.
+     *
+     *  @return  Does the given entry represent a classfile?
+     */
+    private static boolean isClassFileEntry(ZipEntry entry)
+    {
+        return entry.getName().endsWith(".class");
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerTimer.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerTimer.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerTimer.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerTimer.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,70 @@
+/*
+ * 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.InputStream;
+import java.io.OutputStream;
+
+import org.apache.jdo.impl.enhancer.util.Support;
+
+
+
+/**
+ * Timer-wrapper for ClassFileEnhancer instances.
+ *
+ * @author Martin Zaun
+ */
+public final class ClassFileEnhancerTimer
+    extends Support
+    implements ClassFileEnhancer
+{
+    // delegate
+    final protected ClassFileEnhancer delegate;
+
+    /**
+     * Creates an instance.
+     */
+    public ClassFileEnhancerTimer(ClassFileEnhancer delegate)
+    {
+        affirm(delegate);
+        this.delegate = delegate;
+    }
+
+    public boolean enhanceClassFile(InputStream inClassFile,
+                                    OutputStream outClassFile)
+        throws EnhancerUserException, EnhancerFatalError
+    {
+        try {
+            timer.push("ClassFileEnhancer.enhanceClassFile(InputStream,OutputStream)");
+            return delegate.enhanceClassFile(inClassFile, outClassFile);
+        } finally {
+            timer.pop();
+        }
+    }
+
+    public boolean enhanceClassFile(InputStream inClassFile,
+                                    OutputStreamWrapper outClassFile)
+        throws EnhancerUserException, EnhancerFatalError
+    {
+        try {
+            timer.push("ClassFileEnhancer.enhanceClassFile(InputStream,OutputStreamWrapper)");
+            return delegate.enhanceClassFile(inClassFile, outClassFile);
+        } finally {
+            timer.pop();
+        }
+    }
+}



Mime
View raw message