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 EnhancerFatalError
with no detail message.
+ */
+ public EnhancerFatalError()
+ {
+ this.nested = null;
+ }
+
+ /**
+ * Constructs an EnhancerFatalError
with the specified
+ * detail message.
+ */
+ public EnhancerFatalError(String msg)
+ {
+ super(msg);
+ this.nested = null;
+ }
+
+ /**
+ * Constructs an EnhancerFatalError
with an optional
+ * nested exception.
+ */
+ public EnhancerFatalError(Throwable nested)
+ {
+ super(nested.toString());
+ this.nested = nested;
+ }
+
+ /**
+ * Constructs an EnhancerFatalError
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",
+ " : 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: .. ..");
+ printlnErr(indent
+ + "-j -s -d ..");
+ printlnErr(indent
+ + "-j -d ..");
+ //^olsen: consider allowing omission of destination directory for
+ // class file arguments
+ //printlnErr(indent
+ // + "-j [-d ] ..");
+ //^olsen: re-enable support for archive files
+ //printlnErr(indent
+ // + "[-j ] [-d ] ..");
+ }
+
+ /**
+ * 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 EnhancerUserException
without detail
+ * message.
+ */
+ public EnhancerUserException()
+ {
+ }
+
+ /**
+ * Creates a new EnhancerUserException
with the specified
+ * detail message.
+ * @param message the detail message.
+ */
+ public EnhancerUserException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Creates a new EnhancerUserException
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 EnhancerUserException
+ * instance.
+ */
+ public Throwable initCause(Throwable cause)
+ {
+ this.cause = cause;
+ return this;
+ }
+
+ /**
+ * The String
representation includes the name of the class,
+ * the descriptive comment (if any),
+ * and the String
representation of the cause (if any).
+ * @return the String
.
+ */
+ 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 EnhancerUserException
and its backtrace to the
+ * standard error output.
+ * Print cause Throwable's stack trace as well.
+ */
+ public void printStackTrace()
+ {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Prints this EnhancerUserException
and its backtrace to the
+ * specified print stream.
+ * Print cause Throwable's stack trace as well.
+ * @param s PrintStream
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 EnhancerUserException
and its backtrace to the specified
+ * print writer.
+ * Print cause Throwable' stack trace as well.
+ * @param s PrintWriter
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 for lookup of jdo files");
+
+ /**
+ * The jdo properties option.
+ */
+ public final StringOption jdoPropertiesFile
+ = createStringOption("properties", null,
+ " : 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: .. ..");
+ printlnErr(indent
+ + "JDO metadata options:");
+ printlnErr(indent
+ + " --properties [-j ] use property file for JDO metadata");
+ printlnErr(indent
+ + " -j lookup .jdo files in the specified path");
+ printlnErr(indent
+ + "Source option and arguments:");
+ printlnErr(indent
+ + " -s ..");
+ printlnErr(indent
+ + " ..");
+ printlnErr(indent
+ + " ..");
+ }
+
+ /**
+ * 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 String
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 int
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 String
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: .. ..";
+
+ /**
+ * 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 int
+ * 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 int
+ * 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 String
+ * 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 String
+ * 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.
+ *
+ * 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;
+ }
+}