You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/05/22 19:55:54 UTC
svn commit: r171351 [2/16] - in /incubator/jdo/trunk/enhancer20: ./ src/
src/conf/ src/java/ src/java/org/ src/java/org/apache/
src/java/org/apache/jdo/ src/java/org/apache/jdo/enhancer/
src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/enhancer/
src/java/org/apache/jdo/impl/enhancer/classfile/
src/java/org/apache/jdo/impl/enhancer/core/
src/java/org/apache/jdo/impl/enhancer/generator/
src/java/org/apache/jdo/impl/enhancer/meta/
src/java/org/apache/jdo/impl/enhancer/meta/model/
src/java/org/apache/jdo/impl/enhancer/meta/prop/
src/java/org/apache/jdo/impl/enhancer/meta/util/
src/java/org/apache/jdo/impl/enhancer/util/ test/ test/sempdept/
test/sempdept/src/ test/sempdept/src/empdept/
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassArgMain.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassArgMain.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassArgMain.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassArgMain.java Sun May 22 10:55:51 2005
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.enhancer;
+
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+import java.io.File;
+
+import org.apache.jdo.impl.enhancer.util.PathResourceLocator;
+
+
+
+/**
+ * Base class for JDO command line enhancer and tests.
+ *
+ * @author Martin Zaun
+ */
+public class ClassArgMain
+ extends GenericMain
+{
+ /**
+ * The options and arguments.
+ */
+ protected ClassArgOptions options;
+
+ /**
+ * The locator for classes.
+ */
+ protected PathResourceLocator classes;
+
+ /**
+ * Creates an instance.
+ */
+ public ClassArgMain(PrintWriter out,
+ PrintWriter err)
+ {
+ this(out, err, new ClassArgOptions(out, err));
+ }
+
+ /**
+ * Creates an instance.
+ */
+ public ClassArgMain(PrintWriter out,
+ PrintWriter err,
+ ClassArgOptions options)
+ {
+ super(out, err, options);
+ this.options = options;
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Initializes the class locator.
+ */
+ protected void initClassLocator()
+ throws IOException
+ {
+ // create resource locator for specified source path
+ final String path = options.sourcePath.value;
+ if (path != null) {
+ affirm(path.length() > 0);
+ final boolean verbose = options.verbose.value;
+ classes = new PathResourceLocator(out, verbose, path);
+ }
+ }
+
+ /**
+ * Initializes all components.
+ */
+ protected void init()
+ throws EnhancerFatalError, EnhancerUserException
+ {
+ try {
+ initClassLocator();
+ } catch (Exception ex) {
+ throw new EnhancerFatalError(ex);
+ }
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Returns the file name for a class name.
+ * This is done by replacing <code>'.'</code> by <code>'/'</code>.
+ *
+ * @param className the classname
+ * @return the filename
+ */
+ static protected String getClassFileName(String className)
+ {
+ return className.replace('.', '/') + ".class";
+ }
+
+ /**
+ * Opens an input stream for the given filename
+ *
+ * @param fileName the name of the file
+ * @return the input stream
+ * @exception FileNotFoundException if the file could not be found
+ */
+ protected InputStream openFileInputStream(String fileName)
+ throws FileNotFoundException
+ {
+ affirm(fileName != null);
+ //^olsen: support for timing
+ //if (options.doTiming.value) {...}
+ return new BufferedInputStream(new FileInputStream(fileName));
+ }
+
+ /**
+ * Opens an input stream for the given classname. The input stream is
+ * created via an URL that is obtained by the value of the sourcepath
+ * option and zip/jar file arguments.
+ *
+ * @param className the name of the class (dot-notation)
+ * @return the input stream
+ * @exception IOException if an I/O error occured
+ */
+ protected InputStream openClassInputStream(String className)
+ throws IOException
+ {
+ affirm(className != null);
+ final String resName = className.replace('.', '/') + ".class";
+ //^olsen: support for timing
+ //if (options.doTiming.value) {...}
+ final InputStream s = classes.getInputStreamForResource(resName);
+ affirm(s != null);
+ return new BufferedInputStream(s);
+ }
+
+ /**
+ * Closes an input stream.
+ *
+ * @param in the input stream
+ */
+ protected void closeInputStream(InputStream in)
+ {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ex) {
+ printlnErr("", ex);
+ }
+ }
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Runs this class
+ */
+ static public void main(String[] args)
+ {
+ final PrintWriter out = new PrintWriter(System.out, true);
+ out.println("--> ClassArgMain.main()");
+ final ClassArgMain main = new ClassArgMain(out, out);
+ int res = main.run(args);
+ out.println("<-- ClassArgMain.main(): exit = " + res);
+ System.exit(res);
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassArgOptions.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassArgOptions.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassArgOptions.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassArgOptions.java Sun May 22 10:55:51 2005
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.enhancer;
+
+import java.io.PrintWriter;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+
+/**
+ * Set of options used by the JDO enhancer and its test programs.
+ *
+ * @author Martin Zaun
+ */
+public class ClassArgOptions
+ extends GenericOptions
+{
+ /**
+ * Tests if a filename has suffix <code>".class"</code> (ignoring case).
+ *
+ * @param filename the name of the file
+ * @return true if filename has a class file suffix
+ */
+ static private boolean isClassFileName(String filename)
+ {
+ return filename.toLowerCase().endsWith(".class");
+ }
+
+ /**
+ * Tests if a filename has suffix <code>".jar"</code> or
+ * <code>".zip"</code> (ignoring case).
+ *
+ * @param filename the name of the file
+ * @return true if filename has an archive file suffix
+ */
+ static private boolean isArchiveFileName(String filename)
+ {
+ final String s = filename.toLowerCase();
+ return (s.endsWith(".jar") || s.endsWith(".zip"));
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * The source path option.
+ */
+ public final StringOption sourcePath
+ = createStringOption("sourcepath", "s",
+ "<path> : path for lookup of class files");
+
+ /**
+ * The list of class name arguments.
+ */
+ public final List classNames = new ArrayList();
+
+ /**
+ * The list of class file name arguments.
+ */
+ public final List classFileNames = new ArrayList();
+
+ /**
+ * The list of archive file name arguments.
+ */
+ public final List archiveFileNames = new ArrayList();
+
+ /**
+ * Creates an instance.
+ */
+ public ClassArgOptions(PrintWriter out,
+ PrintWriter err)
+ {
+ super(out, err);
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Print a usage message to System.err.
+ */
+ public void printUsageHeader()
+ {
+ printlnErr("Usage: <options>.. <arguments>..");
+ printlnErr(indent
+ + "-s <path> <classname>..");
+ printlnErr(indent
+ + " <classfile>..");
+ //^olsen: re-enable support for archive files
+ //printlnErr(indent
+ // + " <archivefile>..");
+ }
+
+ /**
+ * Print a usage message to System.err.
+ */
+ public void printArgumentUsage()
+ {
+ printlnErr(indent
+ + "<classname> the fully qualified name of a Java class");
+ printlnErr(indent
+ + "<classfile> the name of a .class file");
+ printlnErr(indent
+ + "<archivefile> the name of a .zip or .jar file");
+ }
+
+ /**
+ * Print arguments.
+ */
+ public void printArguments()
+ {
+ println();
+ println(argumentsHeader);
+ printListArgument("classNames", classNames);
+ printListArgument("classFileNames", classFileNames);
+ printListArgument("archiveFileNames", archiveFileNames);
+ }
+
+ /**
+ * Print argument of list type.
+ */
+ public void printListArgument(String name, List list)
+ {
+ print(indent);
+ final StringBuffer s = new StringBuffer();
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ s.append(" " + i.next());
+ }
+ println(name + " = {" + s.toString() + " }");
+ println();
+ }
+
+ /**
+ * Check options and arguments.
+ */
+ public int check()
+ {
+ int res;
+ if ((res = super.check()) != OK) {
+ return res;
+ }
+
+ // group input file arguments
+ for (Iterator names = arguments.iterator(); names.hasNext();) {
+ final String name = (String)names.next();
+ if (isClassFileName(name)) {
+ classFileNames.add(name);
+ } else if (isArchiveFileName(name)) {
+ archiveFileNames.add(name);
+ } else {
+ classNames.add(name);
+ }
+ }
+
+ if (verbose.value) {
+ printAll();
+ }
+
+ // check class arguments
+ final int argTypes = ((classNames.isEmpty() ? 0 : 1)
+ + (classFileNames.isEmpty() ? 0 : 1)
+ + (archiveFileNames.isEmpty() ? 0 : 1));
+ if (argTypes == 0) {
+ printUsageError("No class arguments: specify classes either by class name, class file, or archive file");
+ return USAGE_ERROR;
+ }
+ if (argTypes > 1) {
+ printUsageError("Mixed class arguments: specify classes by either class name, class file, or archive file");
+ return USAGE_ERROR;
+ }
+
+ // check sourcepath option
+ if (sourcePath.value == null && !classNames.isEmpty()) {
+ printUsageError("No source-path specified for lookup of classes");
+ return USAGE_ERROR;
+ }
+ if (sourcePath.value != null && classNames.isEmpty()) {
+ printUsageError("No source-path can be specified with class or archive files");
+ return USAGE_ERROR;
+ }
+
+ //^olsen: re-enable support for archive files
+ if (!archiveFileNames.isEmpty()) {
+ printUsageError("Sorry, support for archive files currently disabled");
+ return USAGE_ERROR;
+ }
+
+ return OK;
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Tests the class.
+ */
+ static public void main(String[] args)
+ {
+ final PrintWriter out = new PrintWriter(System.out, true);
+ out.println("--> ClassArgOptions.main()");
+ final ClassArgOptions options = new ClassArgOptions(out, out);
+ out.println(" options.process() ...");
+ int res = options.process(args);
+ out.println(" return value: " + res);
+ out.println("<-- ClassArgOptions.main()");
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancer.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancer.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancer.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancer.java Sun May 22 10:55:51 2005
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.enhancer;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * A JDO enhancer, or byte-code enhancer, modifies the byte-codes of
+ * Java class files to enable transparent loading and storing of the
+ * fields of the persistent instances.
+ *
+ * @author Martin Zaun
+ */
+public interface ClassFileEnhancer
+{
+ /**
+ * Enhances a given class according to the JDO meta-data. If the
+ * input class has been enhanced or not - the output stream is
+ * always written, either with the enhanced class or with the
+ * non-enhanced class.
+ *
+ * @param in The byte-code of the class to be enhanced.
+ * @param out The byte-code of the enhanced class.
+ * @return <code>true</code> if the class has been enhanced,
+ * <code>false</code> otherwise.
+ */
+ boolean enhanceClassFile(InputStream in,
+ OutputStream out)
+ throws EnhancerUserException, EnhancerFatalError;
+
+
+ /**
+ * Enhances a given class according to the JDO meta-data. If the
+ * input class has been enhanced or not - the output stream is
+ * always written, either with the enhanced class or with the
+ * non-enhanced class.
+ * <p>
+ * Furthermore, the enhancer has to set the classname of
+ * the enhanced class to the output stream wrapper object (it's
+ * possible to get the input stream without knowing the classname).
+ *
+ * @param in The byte-code of the class to be enhanced.
+ * @param out The byte-code of the enhanced class.
+ * @return <code>true</code> if the class has been enhanced,
+ * <code>false</code> otherwise.
+ */
+ boolean enhanceClassFile(InputStream in,
+ OutputStreamWrapper out)
+ throws EnhancerUserException, EnhancerFatalError;
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerHelper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerHelper.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerHelper.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerHelper.java Sun May 22 10:55:51 2005
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.enhancer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+
+/**
+ * This is a helper-class to perform some useful operations outside a
+ * byte code enhancer and delegate the real work to the enhancer.
+ */
+public class ClassFileEnhancerHelper
+{
+ /**
+ * Enhances a classfile.
+ *
+ * @param enhancer The enhancer to delegate the work to.
+ * @param in The input stream with the Java class.
+ * @param out The output stream to write the enhanced class to.
+ *
+ * @return Has the input stream been enhanced?
+ *
+ * @exception EnhancerUserException If something went wrong.
+ * @exception EnhancerFatalError If something went wrong.
+ *
+ * @see ClassFileEnhancer#enhanceClassFile
+ */
+ static public boolean enhanceClassFile(ClassFileEnhancer enhancer,
+ InputStream in,
+ OutputStream out)
+ throws EnhancerUserException,
+ EnhancerFatalError
+ {
+ return enhancer.enhanceClassFile(in, new OutputStreamWrapper(out));
+ }
+
+ /**
+ * Enhances a zip file. The zip file is given as a uip input stream.
+ * It's entries are read and - if necessary - individually enhanced.
+ * The output stream has the same compressÃon (if any) as the input
+ * stream.
+ *
+ * @param enhancer The enhancer.
+ * @param zip_in The zip input stream.
+ * @param zip_out The zip output stream.
+ *
+ * @return <code>true</code> if at least one entry of the zip file has
+ * been enhanced, <code>false</code> otherwise.
+ *
+ * @exception EnhancerUserException If something went wrong.
+ * @exception EnhancerFatalError If something went wrong.
+ *
+ * @see ClassFileEnhancer#enhanceClassFile
+ */
+ static public boolean enhanceZipFile(ClassFileEnhancer enhancer,
+ ZipInputStream zip_in,
+ ZipOutputStream zip_out)
+ throws EnhancerUserException,
+ EnhancerFatalError
+ {
+ boolean enhanced = false;
+ try {
+ CRC32 crc32 = new CRC32();
+ ZipEntry entry;
+ while ((entry = zip_in.getNextEntry()) != null) {
+ InputStream in = zip_in;
+ final ZipEntry out_entry = new ZipEntry(entry);
+
+ // try to enhance
+ if (isClassFileEntry(entry)) {
+ // enhance the classfile
+ // we have to copy the classfile, because if it won't be
+ // enhanced, the OutputStream is empty and we have to
+ // re-read the InputStream, which is impossible with a
+ // ZipInputStream (no mark/reset)
+ in = openZipEntry(zip_in);
+ in.mark(Integer.MAX_VALUE);
+ final ByteArrayOutputStream tmp
+ = new ByteArrayOutputStream();
+ if (enhancer.enhanceClassFile(in, tmp)) {
+ enhanced = true;
+ final byte[] bytes = tmp.toByteArray();
+ tmp.close();
+ in.close();
+ modifyZipEntry(out_entry, bytes, crc32);
+ in = new ByteArrayInputStream(bytes);
+ } else {
+ // the classfile has not been enhanced
+ in.reset();
+ }
+ }
+
+ // copy the entry
+ zip_out.putNextEntry(out_entry);
+ copyZipEntry(in, zip_out);
+ zip_out.closeEntry();
+
+ if (in != zip_in) {
+ in.close();
+ }
+ }
+ } catch (IOException ex) {
+ throw new EnhancerFatalError(ex);
+ }
+
+ return enhanced;
+ }
+
+ /**
+ * Copies a zip entry from one stream to another.
+ *
+ * @param in The inout stream.
+ * @param out The output stream.
+ *
+ * @exception IOException If the stream access failed.
+ */
+ static private void copyZipEntry(InputStream in,
+ OutputStream out)
+ throws IOException
+ {
+ int b;
+ while ((in.available() > 0) && (b = in.read()) > -1) {
+ out.write(b);
+ }
+ }
+
+ /**
+ * Opens the next zip entry of a zip input stream and copies it to
+ * a <code>java.io.ByteArrayOutputStream</code>. It's byte array is made
+ * available via an <code>java.io.ByteArrayInputStream</code> which is
+ * returned.
+ *
+ * @param in The zip input stream.
+ *
+ * @return The newly created input stream with the next zip entry.
+ *
+ * @exception IOException If an I/O operation failed.
+ */
+ static private InputStream openZipEntry(ZipInputStream in)
+ throws IOException
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ copyZipEntry(in, out);
+
+ return new ByteArrayInputStream(out.toByteArray());
+ }
+
+ /**
+ * Modifies the given zip entry so that it can be added to zip file.
+ * The given zip entry represents an enhanced class, so the zip entry
+ * has to get the correct size and checksum (but only if the entry won't
+ * be compressed).
+ *
+ * @param entry The zip entry to modify.
+ * @param bytes The uncompressed byte representation of the classfile.
+ * @param crc32 The checksum evaluator.
+ */
+ private static void modifyZipEntry(ZipEntry entry,
+ byte [] bytes,
+ CRC32 crc32)
+ {
+ entry.setSize(bytes.length);
+ if (entry.getMethod() == 0) {
+ //no compression (ZipInputStream.STORED - not accessible)
+ crc32.reset();
+ crc32.update(bytes);
+ entry.setCrc(crc32.getValue());
+ entry.setCompressedSize(bytes.length);
+ }
+ }
+
+ /**
+ * Determines if a given entry represents a classfile.
+ *
+ * @return Does the given entry represent a classfile?
+ */
+ private static boolean isClassFileEntry(ZipEntry entry)
+ {
+ return entry.getName().endsWith(".class");
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerTimer.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerTimer.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerTimer.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/ClassFileEnhancerTimer.java Sun May 22 10:55:51 2005
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.enhancer;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.jdo.impl.enhancer.util.Support;
+
+
+
+/**
+ * Timer-wrapper for ClassFileEnhancer instances.
+ *
+ * @author Martin Zaun
+ */
+public final class ClassFileEnhancerTimer
+ extends Support
+ implements ClassFileEnhancer
+{
+ // delegate
+ final protected ClassFileEnhancer delegate;
+
+ /**
+ * Creates an instance.
+ */
+ public ClassFileEnhancerTimer(ClassFileEnhancer delegate)
+ {
+ affirm(delegate);
+ this.delegate = delegate;
+ }
+
+ public boolean enhanceClassFile(InputStream inClassFile,
+ OutputStream outClassFile)
+ throws EnhancerUserException, EnhancerFatalError
+ {
+ try {
+ timer.push("ClassFileEnhancer.enhanceClassFile(InputStream,OutputStream)");
+ return delegate.enhanceClassFile(inClassFile, outClassFile);
+ } finally {
+ timer.pop();
+ }
+ }
+
+ public boolean enhanceClassFile(InputStream inClassFile,
+ OutputStreamWrapper outClassFile)
+ throws EnhancerUserException, EnhancerFatalError
+ {
+ try {
+ timer.push("ClassFileEnhancer.enhanceClassFile(InputStream,OutputStreamWrapper)");
+ return delegate.enhanceClassFile(inClassFile, outClassFile);
+ } finally {
+ timer.pop();
+ }
+ }
+}
Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerClassLoader.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerClassLoader.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerClassLoader.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerClassLoader.java Sun May 22 10:55:51 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/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerFatalError.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerFatalError.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerFatalError.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerFatalError.java Sun May 22 10:55:51 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/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerOptions.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerOptions.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerOptions.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerOptions.java Sun May 22 10:55:51 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/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerUserException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerUserException.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerUserException.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/EnhancerUserException.java Sun May 22 10:55:51 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/enhancer20/src/java/org/apache/jdo/impl/enhancer/GenericMain.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/GenericMain.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/GenericMain.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/GenericMain.java Sun May 22 10:55:51 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/enhancer20/src/java/org/apache/jdo/impl/enhancer/GenericOptions.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/GenericOptions.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/GenericOptions.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/GenericOptions.java Sun May 22 10:55:51 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/enhancer20/src/java/org/apache/jdo/impl/enhancer/JdoMetaMain.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/JdoMetaMain.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/JdoMetaMain.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/JdoMetaMain.java Sun May 22 10:55:51 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/enhancer20/src/java/org/apache/jdo/impl/enhancer/JdoMetaOptions.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/JdoMetaOptions.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/JdoMetaOptions.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/JdoMetaOptions.java Sun May 22 10:55:51 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/enhancer20/src/java/org/apache/jdo/impl/enhancer/LogSupport.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/LogSupport.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/LogSupport.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/LogSupport.java Sun May 22 10:55:51 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));
+ }
+ }
+*/
+}