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 [4/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/impl/enhancer/EnhancerClassLoader.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerClassLoader.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerClassLoader.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerClassLoader.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,584 @@
+/*
+ * 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.lang.ref.WeakReference;
+
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import java.util.Properties;
+
+import java.net.URLClassLoader;
+import java.net.URL;
+
+//^olsen: eliminate these dependencies
+import sun.misc.Resource;
+import sun.misc.URLClassPath;
+
+import java.util.jar.Manifest;
+import java.util.jar.Attributes;
+import java.util.jar.Attributes.Name;
+
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import java.security.CodeSource;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.security.cert.Certificate;
+
+import org.apache.jdo.impl.enhancer.core.EnhancerFilter;
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaData;
+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.EnhancerMetaDataTimer;
+import org.apache.jdo.impl.enhancer.util.Support;
+import org.apache.jdo.model.jdo.JDOModel;
+
+
+
+
+
+
+/**
+ * Implements a ClassLoader which automatically enchances the .class files
+ * according to the EnhancerMetaData information in the jar archive.
+ *
+ * @author Yury Kamen
+ * @author Martin Zaun
+ */
+public class EnhancerClassLoader extends URLClassLoader {
+
+    static public final String DO_TIMING_STATISTICS
+        = EnhancerFilter.DO_TIMING_STATISTICS;
+    static public final String VERBOSE_LEVEL
+        = EnhancerFilter.VERBOSE_LEVEL;
+    static public final String VERBOSE_LEVEL_QUIET
+        = EnhancerFilter.VERBOSE_LEVEL_QUIET;
+    static public final String VERBOSE_LEVEL_WARN
+        = EnhancerFilter.VERBOSE_LEVEL_WARN;
+    static public final String VERBOSE_LEVEL_VERBOSE
+        = EnhancerFilter.VERBOSE_LEVEL_VERBOSE;
+    static public final String VERBOSE_LEVEL_DEBUG
+        = EnhancerFilter.VERBOSE_LEVEL_DEBUG;
+
+    static public URL[] pathToURLs(String classpath)
+    {
+        return URLClassPath.pathToURLs(classpath);
+    }
+
+    static final void affirm(boolean cond)
+    {
+        if (!cond)
+            //^olsen: throw AssertionException ?
+            throw new RuntimeException("Assertion failed.");
+    }
+
+    // misc
+    private boolean debug = true;
+    private boolean doTiming = false;
+    private PrintWriter out = new PrintWriter(System.out, true);
+
+    private ClassFileEnhancer enhancer;
+    private EnhancerMetaData metaData;
+    private Properties settings;
+    private WeakReference outByteCodeRef;
+
+    // The search path for classes and resources
+    private final URLClassPath ucp;
+
+    // The context to be used when loading classes and resources
+    private final AccessControlContext acc;
+
+    private final void message()
+    {
+        if (debug) {
+            out.println();
+        }
+    }
+
+    private final void message(String s)
+    {
+        if (debug) {
+            out.println(s);
+        }
+    }
+
+    private final void message(Exception e)
+    {
+        if (debug) {
+            final String msg = ("Exception caught: " + e);
+            out.println(msg);
+            e.printStackTrace(out);
+        }
+    }
+
+    /**
+     * Creates a new EnhancerClassLoader for the specified url.
+     *
+     * @param urls the classpath to search
+     */
+    protected EnhancerClassLoader(URL[] urls)
+    {
+        super(urls);
+        acc = AccessController.getContext();
+        ucp = new URLClassPath(urls);
+        checkUCP(urls);
+    }
+
+    /**
+     * Creates a new EnhancerClassLoader for the specified url.
+     *
+     * @param urls the classpath to search
+     */
+    protected EnhancerClassLoader(URL[] urls,
+                                  ClassLoader loader)
+    {
+        super(urls, loader);
+        acc = AccessController.getContext();
+        ucp = new URLClassPath(urls);
+        checkUCP(urls);
+    }
+
+    /**
+     * Creates a new EnhancerClassLoader for the specified url.
+     *
+     * @param classpath the classpath to search
+     */
+    public EnhancerClassLoader(String classpath,
+                               Properties settings,
+                               PrintWriter out)
+    {
+        this(pathToURLs(classpath));
+        //^olsen: instantiate model
+        affirm(false);
+        EnhancerMetaData metaData
+            = new EnhancerMetaDataJDOModelImpl(out, true, null, null, null);
+        init(metaData, settings, out);
+    }
+
+    /**
+     * Creates a new EnhancerClassLoader for the specified url.
+     *
+     * @param urls the classpath to search
+     */
+    public EnhancerClassLoader(URL[] urls,
+                               Properties settings,
+                               PrintWriter out)
+    {
+        this(urls);
+        //^olsen: instantiate model
+        affirm(false);
+        EnhancerMetaData metaData
+            = new EnhancerMetaDataJDOModelImpl(out, true, null, null, null);
+        init(metaData, settings, out);
+    }
+
+    /**
+     * Creates a new EnhancerClassLoader for the specified url.
+     *
+     * @param classpath the classpath to search
+     */
+    public EnhancerClassLoader(String classpath,
+                               EnhancerMetaData metaData,
+                               Properties settings,
+                               PrintWriter out)
+    {
+        this(pathToURLs(classpath));
+        init(metaData, settings, out);
+    }
+
+    /**
+     * Creates a new EnhancerClassLoader for the specified url.
+     *
+     * @param urls the classpath to search
+     */
+    public EnhancerClassLoader(URL[] urls,
+                               EnhancerMetaData metaData,
+                               Properties settings,
+                               PrintWriter out)
+    {
+        this(urls);
+        init(metaData, settings, out);
+    }
+
+    /**
+     * Appends the specified URL to the list of URLs to search for
+     * classes and resources.
+     *
+     * @param url the URL to be added to the search path of URLs
+     */
+    protected void addURL(URL url)
+    {
+        throw new UnsupportedOperationException("Not implemented yet: EnhancerClassLoader.addURL(URL)");
+        //super.addURL(url);
+        //ucp.addURL(url);
+    }
+
+    private void checkUCP(URL[] urls)
+    {
+        // ensure classpath is not empty
+        if (null == urls) {
+            throw new IllegalArgumentException("urls == null");
+        }
+        if (urls.length == 0) {
+            throw new IllegalArgumentException("urls.length == 0");
+        }
+
+        for (int i = 0; i < urls.length; i++) {
+            super.addURL(urls[i]);
+        }
+    }
+
+    /**
+     * Initialize the EnhancingClassLoader
+     */
+    private void init(EnhancerMetaData metaData,
+                      Properties settings,
+                      PrintWriter out)
+    {
+        this.out = out;
+        final String verboseLevel
+            = (settings == null ? null
+               : settings.getProperty(EnhancerFilter.VERBOSE_LEVEL));
+        this.debug = EnhancerFilter.VERBOSE_LEVEL_DEBUG.equals(verboseLevel);
+        this.settings = settings;
+        this.metaData = metaData;
+        this.enhancer = null;
+
+        if (settings != null) {
+            final String timing
+                = settings.getProperty(EnhancerFilter.DO_TIMING_STATISTICS);
+            this.doTiming = Boolean.valueOf(timing).booleanValue();
+        }
+        if (this.doTiming) {
+            // wrap with timing meta data object
+            this.metaData = new EnhancerMetaDataTimer(metaData);
+        }
+
+        message("EnhancerClassLoader: UCP = {");
+        final URL[] urls = getURLs();
+        for (int i = 0; i < urls.length; i++) {
+            message("    " + urls[i]);
+        }
+        message("}");
+
+        message("EnhancerClassLoader: jdoMetaData = " + metaData);
+    }
+
+    public synchronized Class loadClass(String name, boolean resolve)
+        throws ClassNotFoundException
+    {
+        message();
+        message("EnhancerClassLoader: loading class: " + name);
+
+        try {
+            Class c = null;
+
+            final String classPath = name.replace('.', '/');
+            // At least these packages must be delegated to parent class
+            // loader:
+            //    java/lang,	     (Object, ...)
+            //    java/util,         (Collection)
+            //    java/io,           (PrintWriter)
+            //    javax/sql,         (PMF->javax.sql.DataSource)
+            //    javax/transaction  (Tx->javax.transaction.Synchronization)
+            //
+            //@olsen: delegate loading of "safe" classes to parent
+            //if (metaData.isTransientClass(classPath)) {
+            //
+            //@olsen: only delegate loading of bootstrap classes to parent
+            //if (classPath.startsWith("java/lang/")) {
+            //
+            //@olsen: performance bug 4457471: delegate loading of F4J
+            // persistence classes to parent tp prevent passing these and
+            // other IDE classes plus database drivers etc. to the enhancer!
+            //if (classPath.startsWith("java/lang/")
+            //    || classPath.startsWith("com/sun/forte4j/persistence/")) {
+            //
+            //@olsen: bug 4480618: delegate loading of javax.{sql,transaction}
+            // classes to parent class loader to support user-defined
+            // DataSource and Synchronization objects to be passed to the
+            // TP runtime.  By the same argument, java.{util,io} classes need
+            // also be loaded by the parent class loader.  This has been
+            // the case since the EnhancerClassLoader will never find these
+            // bootstrap classes in the passed Classpath.  However, for
+            // efficiency and clarity, this delegation should be expressed
+            // by testing for entire "java/" package in the check here.
+            if (classPath.startsWith("java/")//NOI18N
+                || classPath.startsWith("javax/sql/")//NOI18N
+                || classPath.startsWith("javax/transaction/")//NOI18N
+                || classPath.startsWith("com/sun/forte4j/persistence/")) {//NOI18N
+                message("EnhancerClassLoader: bootstrap class, using parent loader for class: " + name);//NOI18N
+                return super.loadClass(name, resolve);
+
+//@olsen: dropped alternative approach
+/*
+                message("EnhancerClassLoader: transient class, skipping enhancing: " + name);
+
+                // get a byte array output stream to collect byte code
+                ByteArrayOutputStream outClassFile
+                    = ((null == outByteCodeRef)
+                       ? null : (ByteArrayOutputStream)outByteCodeRef.get());
+                if (null == outClassFile) {
+                    outClassFile = new ByteArrayOutputStream(10000);
+                    outByteCodeRef = new WeakReference(outClassFile);
+                }
+                outClassFile.reset();
+
+                // find byte code of class
+                final InputStream is = getSystemResourceAsStream(name);
+                //@olsen: (is == null) ?!
+
+                // copy byte code of class into byte array
+                final byte[] data;
+                try {
+                    int b;
+                    while ((b = is.read()) >= 0) {
+                        outClassFile.write(b);
+                    }
+                    data = outClassFile.toByteArray();
+                } catch (IOException e) {
+                    final String msg
+                        = ("Exception caught while loading class '"
+                           + name + "' : " + e);
+                    throw new ClassNotFoundException(msg, e);
+                }
+
+                // convert the byte code into class object
+                c = defineClass(name, data, 0, data.length);
+*/
+            }
+
+            //@olsen: check if class has been loaded already
+            if (c == null) {
+                c = findLoadedClass(name);
+                if (c != null) {                
+                    message("EnhancerClassLoader: class already loaded: " + name);//NOI18N
+                }
+            }
+
+            if (c == null) {
+                c = findAndEnhanceClass(name);
+            }
+
+            // as a last resort, if the class couldn't be found, try
+            // loading class by parent class loader
+            if (c == null) {
+                message("EnhancerClassLoader: class not found, using parent loader for class: " + name);//NOI18N
+                return super.loadClass(name, resolve);
+            }
+
+            message();
+            message("EnhancerClassLoader: loaded class: " + name);
+            if (resolve) {
+                resolveClass(c);
+            }
+
+            message();
+            message("EnhancerClassLoader: loaded+resolved class: " + name);
+            return c;
+        } catch (RuntimeException e) {
+            // log exception only
+            message();
+            message("EnhancerClassLoader: EXCEPTION SEEN: " + e);
+            //e.printStackTrace(out);
+            throw e;
+        } catch (ClassNotFoundException e) {
+            // log exception only
+            message();
+            message("EnhancerClassLoader: EXCEPTION SEEN: " + e);
+            //e.printStackTrace(out);
+            throw e;
+        }
+    }
+
+    /**
+     * Finds and loads the class with the specified name from the URL search
+     * path. Any URLs referring to JAR files are loaded and opened as needed
+     * until the class is found.
+     *
+     * @param name the name of the class
+     * @return the resulting class
+     * @exception ClassNotFoundException if the class could not be found
+     */
+    private Class findAndEnhanceClass(final String name)
+        throws ClassNotFoundException
+    {
+        try {
+            if (doTiming) {
+                Support.timer.push("EnhancerClassLoader.findAndEnhanceClass(String)",
+                                   "EnhancerClassLoader.findAndEnhanceClass(" + name + ")");
+            }
+            return (Class)
+            AccessController.doPrivileged(new PrivilegedExceptionAction() {
+                public Object run() throws ClassNotFoundException
+                {
+                    String path = name.replace('.', '/').concat(".class");
+                    //message("path=" + path);
+                    Resource res = ucp.getResource(path, false);
+                    if (res != null) {
+                        try {
+                            return defineClass(name, res);
+                        } catch (IOException e) {
+                            final String msg
+                                = ("Exception caught while loading class '"
+                                   + name + "' : " + e);
+                            throw new ClassNotFoundException(msg, e);
+                        }
+                    } else {
+                        // ok if class resource not found (e.g. java.*)
+                        //throw new ClassNotFoundException(name);
+                        return null;
+                    }
+                }
+            }, acc);
+        } catch (PrivilegedActionException pae) {
+            throw (ClassNotFoundException) pae.getException();
+        } finally {
+            if (doTiming) {
+                Support.timer.pop();
+            }
+        }
+    }
+
+    /**
+     * Defines a Class using the class bytes obtained from the specified
+     * Resource. The resulting Class must be resolved before it can be
+     * used.
+     */
+    private Class defineClass(String name, Resource res)
+        throws IOException, ClassNotFoundException
+    {
+        int i = name.lastIndexOf('.');
+        URL url = res.getCodeSourceURL();
+        if (i != -1) {
+            String pkgname = name.substring(0, i);
+            // Check if package already loaded.
+            Package pkg = getPackage(pkgname);
+            Manifest man = res.getManifest();
+            if (pkg != null) {
+                // Package found, so check package sealing.
+                boolean ok;
+                if (pkg.isSealed()) {
+                    // Verify that code source URL is the same.
+                    ok = pkg.isSealed(url);
+                } else {
+                    // Make sure we are not attempting to seal the package
+                    // at this code source URL.
+                    ok = (man == null) || !isSealed(pkgname, man);
+                }
+                if (!ok) {
+                    throw new SecurityException("sealing violation");
+                }
+            } else {
+                if (man != null) {
+                    definePackage(pkgname, man, url);
+                } else {
+                    definePackage(pkgname, null, null, null, null, null, null, null);
+                }
+            }
+        }
+        // Now read the class bytes and define the class
+        byte[] b = res.getBytes();
+        Certificate[] certs = res.getCertificates();
+        CodeSource cs = new CodeSource(url, certs);
+
+        //@olsen: performance bug 4457471: circumvent enhancer for
+        // non-enhancable classes
+        final String classPath = name.replace('.', '/');
+        if (!metaData.isKnownUnenhancableClass(classPath)) {
+            // Add enhancement here
+            b = enhance(name, b, 0, b.length);
+        }
+
+        return defineClass(name, b, 0, b.length, cs);
+    }
+
+    private byte[] enhance(String name, byte[] data, int off, int len)
+        throws ClassNotFoundException
+    {
+        //message("EnhancerClassLoader: enhance class: " + name);
+
+        final byte[] result;
+        try {
+            // create enhancer if not done yet
+            if (null == enhancer) {
+                enhancer = new EnhancerFilter(metaData, settings, out, null);
+                if (doTiming) {
+                    // wrap with timing filter enhancer object
+                    enhancer = new ClassFileEnhancerTimer(enhancer);
+                }
+            }
+
+            // create input and output byte streams
+            final ByteArrayInputStream inByteCode
+                = new ByteArrayInputStream(data, off, len);
+            ByteArrayOutputStream outByteCode
+                = ((null == outByteCodeRef)
+                   ? null : (ByteArrayOutputStream)outByteCodeRef.get());
+            if (null == outByteCode) {
+                outByteCode = new ByteArrayOutputStream(10000);
+                outByteCodeRef = new WeakReference(outByteCode);
+            }
+            outByteCode.reset();
+
+            // enhance class
+            final boolean changed
+                = enhancer.enhanceClassFile(inByteCode, outByteCode);
+
+            // check whether class has been enhanced
+            result = (changed ? outByteCode.toByteArray() : data);
+        } catch (EnhancerUserException e) {
+            message(e);
+            final String msg = ("Exception caught while loading class '"
+                                + name + "' : " + e);
+            throw new ClassNotFoundException(msg, e);
+        } catch(EnhancerFatalError e) {
+            message(e);
+            final String msg = ("Exception caught while loading class '"
+                                + name + "' : " + e);
+            // discard enhancer because it might have become inconsistent
+            enhancer = null;
+            throw new ClassNotFoundException(msg, e);
+        }
+        return result;
+    }
+
+    /**
+     * Returns true if the specified package name is sealed according to the
+     * given manifest.
+     */
+    private boolean isSealed(String name, Manifest man)
+    {
+        String path = name.replace('.', '/').concat("/");
+        Attributes attr = man.getAttributes(path);
+        String sealed = null;
+        if (attr != null) {
+            sealed = attr.getValue(Name.SEALED);
+        }
+        if (sealed == null) {
+            if ((attr = man.getMainAttributes()) != null) {
+                sealed = attr.getValue(Name.SEALED);
+            }
+        }
+        return "true".equalsIgnoreCase(sealed);
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerFatalError.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerFatalError.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerFatalError.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerFatalError.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;
+
+
+/**
+ * Thrown to indicate that the class-file enhancer failed to perform an
+ * operation due to a serious error.  The enhancer is not guaranteed to
+ * be in a consistent state anymore.
+ */
+public class EnhancerFatalError
+    extends Exception
+{
+    /**
+     * An optional nested exception.
+     */
+    public final Throwable nested;
+
+    /**
+     * Constructs an <code>EnhancerFatalError</code> with no detail message.
+     */
+    public EnhancerFatalError()
+    {
+        this.nested = null;
+    }
+
+    /**
+     * Constructs an <code>EnhancerFatalError</code> with the specified
+     * detail message.
+     */
+    public EnhancerFatalError(String msg)
+    {
+        super(msg);
+        this.nested = null;
+    }
+
+    /**
+     * Constructs an <code>EnhancerFatalError</code> with an optional
+     * nested exception.
+     */
+    public EnhancerFatalError(Throwable nested)
+    {
+        super(nested.toString());
+        this.nested = nested;
+    }
+
+    /**
+     * Constructs an <code>EnhancerFatalError</code> with the specified
+     * detail message and an optional nested exception.
+     */
+    public EnhancerFatalError(String msg, Throwable nested)
+    {
+        super(msg);
+        this.nested = nested;
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerOptions.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerOptions.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerOptions.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerOptions.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,149 @@
+/*
+ * 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;
+
+
+/**
+ * Set of options used by the JDO enhancer and its test programs.
+ *
+ * @author Martin Zaun
+ */
+public class EnhancerOptions
+    extends JdoMetaOptions
+{
+    /**
+     * The quiet option.
+     */
+    public final FlagOption quiet
+        = createFlagOption("quiet", "q",
+                             "           : suppress warnings");
+    /**
+     * The force write option.
+     */
+    public final FlagOption forceWrite
+        = createFlagOption("forcewrite", "f",
+                           "           : overwrite output files");
+
+    /**
+     * The no write option.
+     */
+    public final FlagOption noWrite
+        = createFlagOption("nowrite", "n",
+                           "           : never write output files");
+
+    /**
+     * The destination directory option.
+     */
+    public final StringOption destDir
+        = createStringOption("destdir", "d",
+                             "<path>     : directory for any output files");
+
+    /**
+     * The dump class option.
+     */
+    public final FlagOption dumpClass
+        = createFlagOption("dumpclass", null,
+                           "           : dump out disassembled byte-code");
+
+    /**
+     * The suppress augmentation option.
+     */
+    public final FlagOption noAugment
+        = createFlagOption("noaugment", null,
+                           "           : do not enhance for persistence-capability");
+
+    /**
+     * The suppress annotation option.
+     */
+    public final FlagOption noAnnotate
+        = createFlagOption("noannotate", null,
+                           "           : do not enhance for persistence-awareness");
+
+    /**
+     * Creates an instance.
+     */
+    public EnhancerOptions(PrintWriter out,
+                          PrintWriter err) 
+    {
+        super(out, err);
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printUsageHeader()
+    {
+        printlnErr("Usage: <options>.. <arguments>..");
+        printlnErr(indent
+                   + "-j <path> -s <path> -d <dir>   <classname>..");
+        printlnErr(indent
+                   + "-j <path> -d <dir>             <classfile>..");
+        //^olsen: consider allowing omission of destination directory for
+        // class file arguments
+        //printlnErr(indent
+        //           + "-j <path> [-d <dir>]           <classfile>..");
+        //^olsen: re-enable support for archive files
+        //printlnErr(indent
+        //           + "[-j <path>] [-d <dir>]         <archivefile>..");
+    }
+
+    /**
+     * Check options and arguments.
+     */
+    public int check()
+    {
+        int res;
+        if ((res = super.check()) != OK) {
+            return res;
+        }
+        
+        // check destination directory option
+        if (destDir.value == null && !classNames.isEmpty()) {
+            printUsageError("No destination directory specified for enhanced classes");
+            return USAGE_ERROR;
+        }
+
+        //^olsen: consider allowing omission of destination directory for
+        // class file arguments
+        if (destDir.value == null && !classFileNames.isEmpty()) {
+            printUsageError("No destination directory specified for enhanced classes");
+            return USAGE_ERROR;
+        }
+
+        return OK;
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Tests the class.
+     */
+    static public void main(String[] args)
+    {
+        final PrintWriter out = new PrintWriter(System.out, true);
+        out.println("--> EnhancerOptions.main()");
+        final EnhancerOptions options = new EnhancerOptions(out, out);
+        out.println("    options.process() ...");
+        int res = options.process(args);
+        out.println("    return value: " + res);
+        out.println("<-- EnhancerOptions.main()");
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerUserException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerUserException.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerUserException.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/EnhancerUserException.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,173 @@
+/*
+ * 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 org.apache.jdo.util.I18NHelper;
+
+/**
+ * Thrown to indicate that the class-file enhancer failed to perform an
+ * operation due to an error.  The enhancer is guaranteed to remain in a
+ * consistent state.
+ *
+ * @author Michael Bouschen
+ */
+public class EnhancerUserException
+    extends Exception
+{
+    /** The Throwable that caused this exception to be thrown. */
+    private Throwable cause;
+
+    /** Flag indicating whether printStackTrace is being executed. */
+    private boolean inPrintStackTrace = false;
+
+    /** I18N support */
+    private static I18NHelper msg = 
+        I18NHelper.getInstance("org.apache.jdo.impl.enhancer.Bundle");
+
+    /**
+     * Creates a new <code>EnhancerUserException</code> without detail
+     * message. 
+     */
+    public EnhancerUserException() 
+    {
+    }
+    
+    /**
+     * Creates a new <code>EnhancerUserException</code> with the specified
+     * detail message.
+     * @param message the detail message.
+     */
+    public EnhancerUserException(String message)
+    {
+        super(message);
+    }
+
+    /** 
+     * Creates a new <code>EnhancerUserException</code> with the specified 
+     * detail message and cause Throwable.
+     * @param message the detail message.
+     * @param cause the cause (which is saved for later retrieval by the
+     * {@link #getCause()} method). (A null value is permitted, and
+     * indicates that the cause is nonexistent or unknown.) 
+     */
+    public EnhancerUserException(String message, Throwable cause) 
+    {
+        super(message);
+        this.cause = cause;
+    }
+
+    /** 
+     * Returns the cause of this Exception or null if the cause is
+     * nonexistent or unknown. (The cause is the Throwable that caused this 
+     * Exception to get thrown.) 
+     * @return the cause of this Exception or null if the cause is
+     * nonexistent or unknown. 
+     */
+    public synchronized Throwable getCause() 
+    {
+        // super.printStackTrace calls getCause to handle the cause. 
+        // Returning null prevents the superclass from handling the cause;
+        // instead the local implementation of printStackTrace should
+        // handle the cause. Otherwise, the cause is printed twice.
+        return inPrintStackTrace ? null : cause;
+    }
+
+    /**
+     * Initializes the cause of this throwable to the specified value. (The
+     * cause is the Throwable that caused this Exception to get thrown.) 
+     * @param cause the cause (which is saved for later retrieval by the
+     * {@link #getCause()} method). (A null value is permitted, and
+     * indicates that the cause is nonexistent or unknown.)
+     * @return a reference to this <code>EnhancerUserException</code> 
+     * instance.
+     */
+    public Throwable initCause(Throwable cause)
+    {
+        this.cause = cause;
+        return this;
+    }
+    
+    /** 
+     * The <code>String</code> representation includes the name of the class,
+     * the descriptive comment (if any),
+     * and the <code>String</code> representation of the cause (if any). 
+     * @return the <code>String</code>.
+     */
+    public synchronized String toString() 
+    {
+        StringBuffer sb = new StringBuffer();
+        sb.append(super.toString());
+        // Do not include cause information, if called by printStackTrace;
+        // the stacktrace will include the cause anyway.
+        if ((cause != null) && !inPrintStackTrace) {
+            sb.append("\n");  //NOI18N
+            sb.append(msg.msg("MSG_CauseThrowable")); //NOI18N
+            sb.append("\n");  //NOI18N
+            sb.append(cause.toString()); //NOI18N
+        }
+        return sb.toString();
+    }
+  
+    /**
+     * Prints this <code>EnhancerUserException</code> and its backtrace to the 
+     * standard error output.
+     * Print cause Throwable's stack trace as well.
+     */
+    public void printStackTrace()
+    {
+        printStackTrace(System.err);
+    }
+
+    /**
+     * Prints this <code>EnhancerUserException</code> and its backtrace to the 
+     * specified print stream.
+     * Print cause Throwable's stack trace as well.
+     * @param s <code>PrintStream</code> to use for output
+     */
+    public synchronized void printStackTrace(java.io.PrintStream s) 
+    { 
+        synchronized (s) {
+            inPrintStackTrace = true;
+            super.printStackTrace(s);
+            if (cause != null) {
+                s.println(msg.msg("MSG_CauseThrowableStackTrace")); //NOI18N
+                cause.printStackTrace(s);
+            }
+            inPrintStackTrace = false;
+        }
+    }
+    
+    /**
+     * Prints this <code>EnhancerUserException</code> and its backtrace to the specified
+     * print writer.
+     * Print cause Throwable' stack trace as well.
+     * @param s <code>PrintWriter</code> to use for output
+     */
+    public synchronized void printStackTrace(java.io.PrintWriter s) 
+    { 
+        synchronized (s) {
+            inPrintStackTrace = true;
+            super.printStackTrace(s);
+            if (cause != null) {
+                s.println(msg.msg("MSG_CauseThrowableStackTrace") + ' '); //NOI18N
+                cause.printStackTrace(s);
+            }
+            inPrintStackTrace = false;
+        }
+    }
+    
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/GenericMain.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/GenericMain.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/GenericMain.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/GenericMain.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,115 @@
+/*
+ * 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;
+
+
+/**
+ * Base class for JDO command line enhancer and tests.
+ *
+ * @author Martin Zaun
+ */
+public class GenericMain
+    extends LogSupport
+{
+    // return values for process() method
+    static public final int OK = 0;
+    static public final int USAGE_ERROR = -1;
+    static public final int USER_EXCEPTION = -2;
+    static public final int INTERNAL_ERROR = -3;
+
+    /**
+     *  The options and arguments.
+     */
+    protected GenericOptions options;
+
+    /**
+     * Creates an instance.
+     */
+    public GenericMain(PrintWriter out,
+                       PrintWriter err)
+    {
+        this(out, err, new GenericOptions(out, err));
+    }
+
+    /**
+     * Creates an instance.
+     */
+    public GenericMain(PrintWriter out,
+                       PrintWriter err,
+                       GenericOptions options)
+    {
+        super(out, err);
+        this.options = options;
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Initializes all components.
+     */
+    protected void init()
+        throws EnhancerFatalError, EnhancerUserException
+    {}
+    
+    /**
+     * Do processing (to be overloaded by subclasses).
+     */
+    protected int process()
+    {
+        return OK;
+    }
+    
+    /**
+     * Process command line arguments, run initialization and do processing.
+     */
+    public int run(String[] args)
+    {
+        try {
+            // process passed command-line arguments
+            if (options.process(args) != options.OK) {
+                return USAGE_ERROR;
+            }
+
+            // run initialization and do processing
+            init();
+            return process();
+        } catch (RuntimeException ex) {
+            printlnErr("exception caught", ex);
+            return INTERNAL_ERROR;
+        } catch (Exception ex) {
+            printlnErr("exception caught", ex);
+            return USER_EXCEPTION;
+        }
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Runs this class
+     */
+    static public void main(String[] args)
+    {
+        final PrintWriter out = new PrintWriter(System.out, true);
+        out.println("--> GenericMain.main()");
+        final GenericMain main = new GenericMain(out, out);
+        int res = main.run(args);
+        out.println("<-- GenericMain.main(): exit = " + res);
+        System.exit(res);
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/GenericOptions.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/GenericOptions.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/GenericOptions.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/GenericOptions.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,79 @@
+/*
+ * 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 GenericOptions
+    extends OptionSet
+{
+    /**
+     * The help option.
+     */
+    public final HelpOption help
+        = createHelpOption("help", "h",
+                           "              : print usage message and exit");
+
+    /**
+     * The verbose option.
+     */
+    public final FlagOption verbose
+        = createFlagOption("verbose", "v",
+                           "           : print verbose messages");
+
+    /**
+     * The timing option.
+     */
+    public final FlagOption doTiming
+        = createFlagOption("timing", "t",
+                           "            : do timing messures");
+
+    /**
+     * Creates an instance.
+     */
+    public GenericOptions(PrintWriter out,
+                       PrintWriter err) 
+    {
+        super(out, err);
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Tests the class.
+     */
+    static public void main(String[] args)
+    {
+        final PrintWriter out = new PrintWriter(System.out, true);
+        out.println("--> GenericOptions.main()");
+        final GenericOptions options = new GenericOptions(out, out);
+        out.println("    options.process() ...");
+        int res = options.process(args);
+        out.println("    return value: " + res);
+        out.println("<-- GenericOptions.main()");
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/JdoMetaMain.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/JdoMetaMain.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/JdoMetaMain.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/JdoMetaMain.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,161 @@
+/*
+ * 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.util.Properties;
+
+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.EnhancerMetaDataTimer;
+
+/**
+ * Base class for JDO command line enhancer and tests.
+ *
+ * @author Martin Zaun
+ */
+public class JdoMetaMain
+    extends ClassArgMain
+{
+    /**
+     *  The options and arguments.
+     */
+    protected JdoMetaOptions options;
+
+    /**
+     *  The metadata.
+     */
+    protected EnhancerMetaData jdoMeta;
+
+    /**
+     * Creates an instance.
+     */
+    public JdoMetaMain(PrintWriter out,
+                       PrintWriter err)
+    {
+        this(out, err, new JdoMetaOptions(out, err));
+    }
+
+    /**
+     * Creates an instance.
+     */
+    public JdoMetaMain(PrintWriter out,
+                       PrintWriter err,
+                       JdoMetaOptions options)
+    {
+        super(out, err, options);
+        this.options = options;
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Initializes the jdo metadata component.
+     */
+    protected void initJdoMetaData()
+        throws EnhancerMetaDataFatalError
+    {
+        final boolean verbose = options.verbose.value;
+        final String path = options.jdoPath.value;
+        final String jdoPropsFile = options.jdoPropertiesFile.value;
+
+        if (jdoPropsFile != null && jdoPropsFile.length() > 0) {
+            // read JDO metadata from properties file
+            if (path != null && path.length() > 0) {
+                // load the properties file using the path specified with
+                // -j (if available)
+                try {
+                    final Properties props = new Properties();
+                    props.load(classes.getInputStreamForResource(jdoPropsFile));
+                    jdoMeta = new EnhancerMetaDataPropertyImpl(out, 
+                                                               verbose, 
+                                                               props);
+                } catch (IOException ex) {
+                    throw new EnhancerMetaDataFatalError(ex);
+                }  
+            } else {
+                // no -j option => take the properties file name as it is
+                jdoMeta = new EnhancerMetaDataPropertyImpl(out, 
+                                                           verbose, 
+                                                           jdoPropsFile);
+            }
+        } else {
+            //^olsen: simplify interface; just append archives to jdo-path
+            jdoMeta = new EnhancerMetaDataJDOModelImpl(
+                out, verbose,
+                null,
+                options.archiveFileNames,
+                path);
+        }
+
+//^olsen: add archives to path locator...
+/*
+            // create resource locator for specified zip files
+            if (archiveFileNames != null && !archiveFileNames.isEmpty()) {
+                final StringBuffer s = new StringBuffer();
+                final Iterator i = archiveFileNames.iterator();
+                s.append(i.next());
+                while (i.hasNext()) {
+                    s.append(File.pathSeparator + i.next());
+                }
+                final ResourceLocator zips
+                    = new PathResourceLocator(out, verbose, s.toString());
+                printMessage(getI18N("enhancer.using_zip_files",
+                                     s.toString()));
+                locators.add(zips);
+            }
+*/
+
+        // wrap with timing meta data object
+        if (options.doTiming.value) {
+            jdoMeta = new EnhancerMetaDataTimer(jdoMeta);
+        }
+    }
+
+    /**
+     * Initializes all components.
+     */
+    protected void init()
+        throws EnhancerFatalError, EnhancerUserException
+    {
+        super.init();
+        try {
+            initJdoMetaData();
+        } catch (Exception ex) {
+            throw new EnhancerFatalError(ex);
+        }
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Runs this class
+     */
+    static public void main(String[] args)
+    {
+        final PrintWriter out = new PrintWriter(System.out, true);
+        out.println("--> JdoMetaMain.main()");
+        final JdoMetaMain main = new JdoMetaMain(out, out);
+        int res = main.run(args);
+        out.println("<-- JdoMetaMain.main(): exit = " + res);
+        System.exit(res);
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/JdoMetaOptions.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/JdoMetaOptions.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/JdoMetaOptions.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/JdoMetaOptions.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,112 @@
+/*
+ * 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;
+
+
+/**
+ * Set of options used by the JDO enhancer and its test programs.
+ *
+ * @author Martin Zaun
+ */
+public class JdoMetaOptions
+    extends ClassArgOptions
+{
+    /**
+     * The jdo path option.
+     */
+    public final StringOption jdoPath
+        = createStringOption("jdopath", "j",
+                             "<path>     : path for lookup of jdo files");
+
+    /**
+     * The jdo properties option.
+     */
+    public final StringOption jdoPropertiesFile
+        = createStringOption("properties", null,
+                             "<file>  : use property file for JDO metadata");
+
+    /**
+     * Creates an instance.
+     */
+    public JdoMetaOptions(PrintWriter out,
+                          PrintWriter err) 
+    {
+        super(out, err);
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Print a usage message to System.err.
+     */
+    public void printUsageHeader()
+    {
+        printlnErr("Usage: <options>.. <arguments>..");
+        printlnErr(indent
+                   + "JDO metadata options:");
+        printlnErr(indent
+                   + "  --properties <file> [-j <path>] use property file for JDO metadata");
+        printlnErr(indent
+                   + "  -j <path>                       lookup .jdo files in the specified path");
+        printlnErr(indent
+                   + "Source option and arguments:");
+        printlnErr(indent
+                   + "  -s <path>   <classname>..");
+        printlnErr(indent
+                   + "              <classfile>..");
+        printlnErr(indent
+                   + "              <archivefile>..");
+    }
+
+    /**
+     * Check options and arguments.
+     */
+    public int check()
+    {
+        int res;
+        if ((res = super.check()) != OK) {
+            return res;
+        }
+        
+        // check jdopath option
+        if (jdoPropertiesFile.value == null && 
+            jdoPath.value == null && archiveFileNames.isEmpty()) {
+            printUsageError("No JDO metadata option: specify either properties file or jdo-path for lookup of jdo files");
+            return USAGE_ERROR;
+        }
+
+        return OK;
+    }
+
+    // ----------------------------------------------------------------------
+
+    /**
+     * Tests the class.
+     */
+    static public void main(String[] args)
+    {
+        final PrintWriter out = new PrintWriter(System.out, true);
+        out.println("--> JdoMetaOptions.main()");
+        final JdoMetaOptions options = new JdoMetaOptions(out, out);
+        out.println("    options.process() ...");
+        int res = options.process(args);
+        out.println("    return value: " + res);
+        out.println("<-- JdoMetaOptions.main()");
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/LogSupport.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/LogSupport.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/LogSupport.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/LogSupport.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,166 @@
+/*
+ * 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 org.apache.jdo.impl.enhancer.util.Support;
+
+
+
+/**
+ * Provides some basic utilities for main classes.
+ *
+ * @author Martin Zaun
+ */
+class LogSupport
+    extends Support
+{
+    /**
+     * The stream to write messages to.
+     */
+    protected final PrintWriter out;
+
+    /**
+     * The stream to write error messages to.
+     */
+    protected final PrintWriter err;
+    
+    /**
+     * Creates an instance.
+     */
+    public LogSupport(PrintWriter out,
+                      PrintWriter err) 
+    {
+        affirm(out != null);
+        affirm(err != null);
+        this.out = out;
+        this.err = err;
+    }
+
+    /**
+     * Prints out an error message.
+     */
+    protected void printlnErr(String msg,
+                              Throwable ex,
+                              boolean verbose)
+    {
+        out.flush();
+        if (msg != null) {
+            err.println(msg);
+        }
+        if (ex != null) {
+            if (verbose) {
+                ex.printStackTrace(err);
+            }
+            else {
+                err.println(ex.toString());
+            }
+        }
+    }
+
+    /**
+     * Prints out an error message.
+     */
+    protected void printlnErr(String msg,
+                              Throwable ex)
+    {
+        out.flush();
+        err.println(msg + ": " + ex.getMessage());
+        ex.printStackTrace(err);
+    }
+
+    /**
+     * Prints out an error message.
+     */
+    protected void printlnErr(String msg)
+    {
+        out.flush();
+        err.println(msg);
+    }
+
+    /**
+     * Prints out an error message.
+     */
+    protected void printlnErr()
+    {
+        out.flush();
+        err.println();
+    }
+
+    /**
+     * Prints out a message.
+     */
+    protected void print(String msg)
+    {
+        out.print(msg);
+    }
+
+    /**
+     * Prints out a message.
+     */
+    protected void println(String msg)
+    {
+        out.println(msg);
+    }
+
+    /**
+     * Prints out a message.
+     */
+    protected void println()
+    {
+        out.println();
+    }
+
+    /**
+     * Flushes streams.
+     */
+    protected void flush()
+    {
+        out.flush();
+        err.flush();
+    }
+
+    // ----------------------------------------------------------------------
+
+//^olsen: support for I18N
+
+    /**
+     *  Prints out a warning message.
+     *
+     *  @param msg the message
+     */
+/*
+    public void printWarning(String msg)
+    {
+        out.println(getI18N("enhancer.warning", msg));
+    }
+*/
+    /**
+     *  Prints out a verbose message.
+     *
+     *  @param msg the message
+     */
+/*
+    public void printMessage(String msg)
+    {
+        if (options.verbose.value) {
+            out.println(getI18N("enhancer.message", msg));
+        }
+    }
+*/
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/OptionSet.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/OptionSet.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/OptionSet.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/OptionSet.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/enhancer/OutputStreamWrapper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/OutputStreamWrapper.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/OutputStreamWrapper.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/OutputStreamWrapper.java Fri Mar 18 17:02:29 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;
+    }
+}



Mime
View raw message