From jdo-commits-return-166-apmail-db-jdo-commits-archive=www.apache.org@db.apache.org Sat Mar 19 04:59:40 2005 Return-Path: Delivered-To: apmail-db-jdo-commits-archive@www.apache.org Received: (qmail 81415 invoked from network); 19 Mar 2005 04:59:40 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 19 Mar 2005 04:59:40 -0000 Received: (qmail 81861 invoked by uid 500); 19 Mar 2005 04:59:39 -0000 Mailing-List: contact jdo-commits-help@db.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jdo-dev@db.apache.org Delivered-To: mailing list jdo-commits@db.apache.org Delivered-To: moderator for jdo-commits@db.apache.org Received: (qmail 82535 invoked by uid 99); 19 Mar 2005 01:06:01 -0000 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Message-ID: <20050319010557.28013.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Mailer: svnmailer-1.0.0-dev Date: Sat, 19 Mar 2005 01:05:57 -0000 Subject: svn commit: r158176 [3/79] - in incubator/jdo/trunk/ri11: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/ejb/ src/java/org/apache/jdo/enhancer/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/enhancer/ src/java/org/apache/jdo/impl/enhancer/classfile/ src/java/org/apache/jdo/impl/enhancer/core/ src/java/org/apache/jdo/impl/enhancer/generator/ src/java/org/apache/jdo/impl/enhancer/meta/ src/java/org/apache/jdo/impl/enhancer/meta/model/ src/java/org/apache/jdo/impl/enhancer/meta/prop/ src/java/org/apache/jdo/impl/enhancer/meta/util/ src/java/org/apache/jdo/impl/enhancer/util/ src/java/org/apache/jdo/impl/fostore/ src/java/org/apache/jdo/impl/jdoql/ src/java/org/apache/jdo/impl/jdoql/jdoqlc/ src/java/org/apache/jdo/impl/jdoql/scope/ src/java/org/apache/jdo/impl/jdoql/tree/ src/java/org/apache/jdo/impl/model/ src/java/org/apache/jdo/impl/model/java/ src/java/org/apache/jdo/impl/model/java/runtime/ src/java/org/apache/jdo/impl/model/jdo/ src/java/org/apache/jdo/impl/model/jdo/caching/ src/java/org/apache/jdo/impl/model/jdo/util/ src/java/org/apache/jdo/impl/model/jdo/xml/ src/java/org/apache/jdo/impl/pm/ src/java/org/apache/jdo/impl/sco/ src/java/org/apache/jdo/impl/state/ src/java/org/apache/jdo/jdoql/ src/java/org/apache/jdo/jdoql/tree/ src/java/org/apache/jdo/model/ src/java/org/apache/jdo/model/java/ src/java/org/apache/jdo/model/jdo/ src/java/org/apache/jdo/pm/ src/java/org/apache/jdo/sco/ src/java/org/apache/jdo/state/ src/java/org/apache/jdo/store/ src/java/org/apache/jdo/util/ test/ test/conf/ test/enhancer/ test/enhancer/sempdept/ test/enhancer/sempdept/src/ test/enhancer/sempdept/src/empdept/ test/fsuid2/ test/fsuid2/org/ test/fsuid2/org/apache/ test/fsuid2/org/apache/jdo/ test/fsuid2/org/apache/jdo/pc/ test/java/ test/java/org/ test/java/org/apache/ test/java/org/apache/jdo/ test/java/org/apache/jdo/impl/ test/java/org/apache/jdo/impl/fostore/ test/java/org/apache/jdo/pc/ test/java/org/apache/jdo/pc/appid/ test/java/org/apache/jdo/pc/empdept/ test/java/org/apache/jdo/pc/serializable/ test/java/org/apache/jdo/pc/xempdept/ test/java/org/apache/jdo/test/ test/java/org/apache/jdo/test/query/ test/java/org/apache/jdo/test/util/ test/jdo/ test/jdo/org/ test/jdo/org/apache/ test/jdo/org/apache/jdo/ test/jdo/org/apache/jdo/pc/ test/jdo/org/apache/jdo/pc/appid/ test/jdo/org/apache/jdo/pc/empdept/ test/jdo/org/apache/jdo/pc/serializable/ test/jdo/org/apache/jdo/pc/xempdept/ xdocs/ To: jdo-commits@db.apache.org From: mbo@apache.org X-Virus-Checked: Checked X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/Main.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/enhancer/Main.java?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/Main.java (ad= ded) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/Main.java Fri= Mar 18 17:02:29 2005 @@ -0,0 +1,957 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * 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=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * limitations under the License. + */ + +package org.apache.jdo.enhancer; + +import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.PrintWriter; +import java.io.FileReader; +import java.io.BufferedReader; + +import java.util.Map; +import java.util.List; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Properties; +import java.util.StringTokenizer; + +import java.util.zip.ZipFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; +import java.util.zip.ZipException; + +import java.net.URL; + +import org.apache.jdo.impl.enhancer.ClassFileEnhancer; +import org.apache.jdo.impl.enhancer.ClassFileEnhancerHelper; +import org.apache.jdo.impl.enhancer.ClassFileEnhancerTimer; +import org.apache.jdo.impl.enhancer.EnhancerFatalError; +import org.apache.jdo.impl.enhancer.EnhancerUserException; +import org.apache.jdo.impl.enhancer.OutputStreamWrapper; +import org.apache.jdo.impl.enhancer.core.EnhancerFilter; +import org.apache.jdo.impl.enhancer.meta.EnhancerMetaData; +import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataFatalError; +import org.apache.jdo.impl.enhancer.meta.model.EnhancerMetaDataJDOModelImp= l; +import org.apache.jdo.impl.enhancer.meta.prop.EnhancerMetaDataPropertyImpl; +import org.apache.jdo.impl.enhancer.meta.util.EnhancerMetaDataBaseModel; +import org.apache.jdo.impl.enhancer.meta.util.EnhancerMetaDataTimer; +import org.apache.jdo.impl.enhancer.util.CombinedResourceLocator; +import org.apache.jdo.impl.enhancer.util.ListResourceLocator; +import org.apache.jdo.impl.enhancer.util.PathResourceLocator; +import org.apache.jdo.impl.enhancer.util.ResourceLocator; +import org.apache.jdo.impl.enhancer.util.ResourceLocatorTimer; +import org.apache.jdo.impl.enhancer.util.Support; + + + + + +/** + * Main is the starting point for the persistent filter tool. + */ +public class Main + extends Support +{ + // return values of main() + static public final int OK =3D 0; + static public final int USAGE_ERROR =3D -1; + static public final int METADATA_ERROR =3D -2; + static public final int CLASS_LOCATOR_ERROR =3D -3; + static public final int INTERNAL_ERROR =3D -4; + + /** + * The stream to write messages to. + */ + private final PrintWriter out =3D new PrintWriter(System.out, true); + + /** + * The stream to write error messages to. + */ + private final PrintWriter err =3D new PrintWriter(System.err, true); + + /** + * The command line options. + */ + private final CmdLineOptions opts =3D new CmdLineOptions(); + + /** + * The byte code enhancer. + */ + private ClassFileEnhancer enhancer; + + /** + * The locator for classes. + */ + protected ResourceLocator classLocator; + + /** + * The metadata for the enhancer. + */ + private EnhancerMetaData jdoMetaData; + + /** + * Construct a filter tool instance + */ + public Main() + {} + + // -------------------------------------------------------------------= --- + + /** + * This is where it all starts. + */ + public static void main(String[] argv) + { + int res; + final Main main =3D new Main(); + + //@olsen: added support for timing statistics + try { + res =3D main.process(argv); + } catch (RuntimeException ex) { + main.out.flush(); + main.err.println("Internal error while postprocessing: " + + ex.getMessage()); + ex.printStackTrace(main.err); + main.err.flush(); + res =3D INTERNAL_ERROR; + } finally { + //@olsen: added support for timing statistics + if (main.opts.doTiming) { + Support.timer.print(); + } + } + System.exit(res); + } + + /** + * Process command line options and run enhancer. + */ + public int process(String[] argv) + { + int res; + + if ((res =3D opts.processArgs(argv)) !=3D OK) { + printMessage("aborted with errors."); + return res; + } + + //@olsen: added support for timing statistics + try { + if (opts.doTiming) { + timer.push("Main.process(String[])"); + } + + if ((res =3D createEnhancer()) !=3D OK) { + printMessage("aborted with errors."); + return res; + } + + if ((res =3D enhanceInputFiles(opts.classNames, + opts.classFileNames, + opts.zipFileNames, + opts.jdoFileNames)) !=3D OK) { + printMessage("aborted with errors."); + return res; + } + + printMessage("done."); + return 0; + } finally { + if (opts.doTiming) { + timer.pop(); + } + } + } + + // -------------------------------------------------------------------= --- + + /** + * A class for holding the command line options. + */ + private class CmdLineOptions + { + final List classNames =3D new ArrayList(); =20 + final List classFileNames =3D new ArrayList(); =20 + final List zipFileNames =3D new ArrayList(); =20 + final List jdoFileNames =3D new ArrayList(); =20 + String sourcePath =3D null; + String destinationDirectory =3D null; + String propertiesFileName =3D null; + boolean doTiming =3D false; + boolean verbose =3D false; + boolean quiet =3D false; + boolean forceWrite =3D false; + boolean noWrite =3D false; + boolean dumpClass =3D false; + boolean noAugment =3D false; + boolean noAnnotate =3D false; + + /** + * Print a usage message to System.err. + */ + public void usage() { + err.println("Usage: main ..."); + err.println("Options:"); + err.println(" -h, --help print usage message an= d exit gently"); + err.println(" -v, --verbose print verbose messages= "); + err.println(" -q, --quiet supress warnings"); + err.println(" -s, --sourcepath source path for jdo an= d classfiles"); + err.println(" -d, --destdir destination directory = for output files"); + err.println(" -f, --force overwrite output files= "); + err.println(" -n, --nowrite never write output fil= es"); + err.println(" -t, --timing do timing messures"); + err.println(); + err.println("Debugging Options:"); + err.println(" --properties use property file for = meta data"); + err.println(" --dumpclass print out disassembled= code of classes"); + err.println(" --noaugment do not enhance for per= sistence-capability"); + err.println(" --noannotate do not enhance for per= sistence-awareness"); + err.println(); + err.println("Arguments:"); + //err.println(" the fully qualified name of a Ja= va class"); + err.println(" the name of a .jdo file"); + err.println(" the name of a .class file"); + //err.println(" the name of a .zip or .jar file"= ); + err.println(); + err.println("Returns a non-zero value in case of errors."); + } + + /** + * Process command line options. + */ + protected int processArgs(String[] argv) + { + final Collection inputNames =3D new ArrayList(); + for (int i =3D 0; i < argv.length; i++) { + final String arg =3D argv[i]; + if (arg.equals("-h") + || arg.equals("--help")) { + usage(); + return OK; + } + if (arg.equals("-v") + || arg.equals("--verbose")) { + verbose =3D true; + quiet =3D false; + continue; + } + if (arg.equals("-q") + || arg.equals("--quiet")) { + quiet =3D true; + verbose =3D false; + continue; + } + if (arg.equals("-t") || + arg.equals("--timing")) { + doTiming =3D true; + continue; + } + if (arg.equals("-f") + || arg.equals("--force")) { + forceWrite =3D true; + noWrite =3D false; + continue; + } + if (arg.equals("-n") + || arg.equals("--nowrite")) { + noWrite =3D true; + forceWrite =3D false; + continue; + } + if (arg.equals("--dumpclass")) { + dumpClass =3D true; + continue; + } + if (arg.equals("--noaugment")) { + noAugment =3D true; + continue; + } + if (arg.equals("--noannotate")) { + noAnnotate =3D true; + continue; + } + if (arg.equals("-s") + || arg.equals("--sourcepath")) { + if (argv.length - i < 2) { + printError("Missing argument to the -s/--sourcepat= h option", null); + usage(); + return USAGE_ERROR; + } + sourcePath =3D argv[++i]; + continue; + } + if (arg.equals("-d") + || arg.equals("--destdir")) { + if (argv.length - i < 2) { + printError("Missing argument to the -d/-destdir op= tion", null); + usage(); + return USAGE_ERROR; + } + destinationDirectory =3D argv[++i]; + continue; + } + if (arg.equals("--properties")) { + if (argv.length - i < 2) { + printError("Missing argument to the --properties o= ption", null); + usage(); + return USAGE_ERROR; + } + propertiesFileName =3D argv[++i]; + continue; + } + if (arg.length() > 0 && arg.charAt(0) =3D=3D '-') { + printError("Unrecognized option:" + arg, null); + usage(); + return USAGE_ERROR; + } + if (arg.length() =3D=3D 0) { + printMessage("Ignoring empty command line argument."); + continue; + } + + inputNames.add(arg); + } + + // group input file arguments + for (Iterator names =3D inputNames.iterator(); names.hasNext()= ;) { + final String name =3D (String)names.next(); + if (isJdoFileName(name)) { + jdoFileNames.add(name); + } else if (isClassFileName(name)) { + classFileNames.add(name); + } else if (isZipFileName(name)) { + zipFileNames.add(name); + } else { + classNames.add(name); + } + } + + if (verbose) { + printArgs(); + } + return checkArgs(); + } + + /** + * Check command line options. + */ + protected int checkArgs() + { + // at least one class must be specified + if (classNames.isEmpty() + && classFileNames.isEmpty() + && zipFileNames.isEmpty()) { + final String msg + =3D "No classes specified"; + printError(msg, null); + usage(); + return USAGE_ERROR; + } + + // at least one meta-data source must be specified for classfi= les + if (classFileNames.size() > 0 + && (jdoFileNames.isEmpty() + && propertiesFileName =3D=3D null + && sourcePath =3D=3D null)) { + final String msg + =3D "No JDO meta-data source specified for class files= "; + printError(msg, null); + usage(); + return USAGE_ERROR; + } + + // either jdo files or jdo properties specified + if (!jdoFileNames.isEmpty() && propertiesFileName !=3D null) { + final String msg + =3D "Cannot have both jdo files and properties specifi= ed"; + printError(msg, null); + usage(); + return USAGE_ERROR; + } + + return OK; + } + + /** + * Print command line options. + */ + protected void printArgs() + { + out.println("Enhancer: options:"); + out.println(" verbose =3D " + verbose); + out.println(" quiet =3D " + quiet); + out.println(" forceWrite =3D " + forceWrite); + out.println(" noWrite =3D " + noWrite); + out.println(" sourcePath =3D " + sourcePath); + out.println(" destinationDirectory =3D " + destinationDirec= tory); + out.println(" propertiesFileName =3D " + propertiesFileName= ); + out.println(" doTiming =3D " + doTiming); + out.println(" classNames =3D {"); + for (Iterator i =3D classNames.iterator(); i.hasNext();) { + out.println(" " + i.next()); + } + out.println(" }"); + out.println(" jdoFileNames =3D {"); + for (Iterator i =3D jdoFileNames.iterator(); i.hasNext();) { + out.println(" " + i.next()); + } + out.println(" }"); + out.println(" classFileNames =3D {"); + for (Iterator i =3D classFileNames.iterator(); i.hasNext();) { + out.println(" " + i.next()); + } + out.println(" }"); + out.println(" zipFileNames =3D {"); + for (Iterator i =3D zipFileNames.iterator(); i.hasNext();) { + out.println(" " + i.next()); + } + out.println(" }"); + out.println(" dumpClass =3D " + dumpClass); + out.println(" noAugment =3D " + noAugment); + out.println(" noAnnotate =3D " + noAnnotate); + } + } + + private int initClassLocator() + { + final boolean verbose =3D opts.verbose; + final List classFileNames =3D opts.classFileNames; + final List zipFileNames =3D opts.zipFileNames; + final String sourcePath =3D opts.sourcePath; + try { + final List locators =3D new ArrayList(); + + // create resource locator for specified class files + if (classFileNames !=3D null && !classFileNames.isEmpty()) { + final ResourceLocator classes + =3D new ListResourceLocator(out, verbose, classFileNam= es); + if (verbose) { + out.println("Class Locator: using class files: {"); + for (Iterator i =3D classFileNames.iterator(); i.hasNe= xt();) { + out.println(" " + i.next()); + } + out.println("}"); + } + locators.add(classes); + } + + // create resource locator for specified zip files + if (zipFileNames !=3D null && !zipFileNames.isEmpty()) { + final StringBuffer s =3D new StringBuffer(); + final Iterator i =3D zipFileNames.iterator(); + s.append(i.next()); + while (i.hasNext()) { + s.append(File.pathSeparator + i.next()); + } + final ResourceLocator zips + =3D new PathResourceLocator(out, verbose, s.toString()= ); + if (verbose) + out.println("Class Locator: using jar/zip files: " + + s.toString()); + locators.add(zips); + } + + // create resource locator for specified source path + if (sourcePath !=3D null && sourcePath.length() > 0) { + final ResourceLocator path + =3D new PathResourceLocator(out, verbose, sourcePath); + if (verbose) + out.println("Class Locator: using source path: " + + sourcePath); + locators.add(path); + } + + // print warning if no classes specified + affirm(!locators.isEmpty()); + //if (locators.isEmpty()) { + // printWarning(getI18N("enhancer.using_no_classes")); + //} + + // init class locators + classLocator + =3D new CombinedResourceLocator(out, verbose, locators); + + // wrap with timing class locator + if (opts.doTiming) { + classLocator =3D new ResourceLocatorTimer(classLocator); + } + } catch (IOException ex) { + printError("Cannot initialize resource locator for classes", e= x); + return CLASS_LOCATOR_ERROR; + } + return OK; + } + + private int initEnhancerMetaData() + { + final boolean verbose =3D opts.verbose; + final String propertiesFileName =3D opts.propertiesFileName; + final List jdoFileNames =3D opts.jdoFileNames; + final List zipFileNames =3D opts.zipFileNames; + final String sourcePath =3D opts.sourcePath; + try { + if (propertiesFileName !=3D null) { + jdoMetaData + =3D new EnhancerMetaDataPropertyImpl(out, verbose, + propertiesFileName); + } else { + jdoMetaData + =3D new EnhancerMetaDataJDOModelImpl(out, verbose, + jdoFileNames, + zipFileNames, + sourcePath); + } + + // wrap with timing meta data object + if (opts.doTiming) { + jdoMetaData =3D new EnhancerMetaDataTimer(jdoMetaData); + } + } catch (EnhancerMetaDataFatalError ex) { + printError("Cannot initialize JDO meta-data source", ex); + return METADATA_ERROR; + } + return OK; + } + =20 + private int createEnhancer() + { + int res0 =3D initClassLocator(); + if (res0 < 0) { + return res0; + } + affirm(classLocator !=3D null); + + int res =3D initEnhancerMetaData(); + if (res < 0) { + return res; + } + affirm(jdoMetaData !=3D null); + + final Properties props =3D new Properties(); + if (opts.verbose) { + props.put(EnhancerFilter.VERBOSE_LEVEL, + EnhancerFilter.VERBOSE_LEVEL_VERBOSE); + } + =20 + if (opts.doTiming) { + props.put(EnhancerFilter.DO_TIMING_STATISTICS, + Boolean.TRUE.toString()); + } + + if (opts.dumpClass) { + props.put(EnhancerFilter.DUMP_CLASS, + Boolean.TRUE.toString()); + } + + if (opts.noAugment) { + props.put(EnhancerFilter.NO_AUGMENT, + Boolean.TRUE.toString()); + } + + if (opts.noAnnotate) { + props.put(EnhancerFilter.NO_ANNOTATE, + Boolean.TRUE.toString()); + } + + try { =20 + enhancer =3D new EnhancerFilter(jdoMetaData, props, out, err); + if (opts.doTiming) { + // wrap with timing byte-code enhancer + enhancer =3D new ClassFileEnhancerTimer(enhancer); + } + return 0; + } catch (EnhancerUserException ex) { + printError("Error while creating the enhancer", ex); + return -1; + } catch (EnhancerFatalError ex) { + // enhancer is not anymore guaranteed to be consistent + printError("Fatal error while creating the enhancer", ex); + enhancer =3D null; + return -1; + } + } + + // -------------------------------------------------------------------= --- + + /** + * Enhances all files entered in the command line. + * + * @param classNames List of class names. + * @param classFileNames List of class file names. + * @param zipFileNames List of zip file names. + * @param jdoFileNames List of jdo file names. + */ + private int enhanceInputFiles(List classNames, + List classFileNames, + List zipFileNames, + List jdoFileNames) + { + int res =3D 0; + try { + String name =3D null; + for (Iterator i =3D zipFileNames.iterator(); i.hasNext();) { + try { + name =3D (String)i.next(); + enhanceZipFile(name); + } catch (EnhancerUserException ex) { + printError("Error while enhancing " + name, ex); + res++; + continue; + } + } + for (Iterator i =3D classFileNames.iterator(); i.hasNext();) { + try { + name =3D (String)i.next(); + enhanceClassFile(openFileInputStream(name)); + } catch (EnhancerUserException ex) { + printError("Error while enhancing " + name, ex); + res++; + continue; + } + } + for (Iterator i =3D classNames.iterator(); i.hasNext();) { + try { + name =3D (String)i.next(); + enhanceClassFile(openClassInputStream(name)); + } catch (EnhancerUserException ex) { + printError("Error while enhancing " + name, ex); + res++; + continue; + } + } + } catch (IOException ex) { + printError("IO Error while enhancing", ex); + return ++res; + } catch (EnhancerFatalError ex) { + // enhancer is not anymore guaranteed to be consistent + printError("Fatal error while enhancing", ex); + enhancer =3D null; + return ++res; + } + return res; + } + + /** + * Enhances a classfile. + * + * @param in The input stream of the classfile. + */ + private void enhanceClassFile(InputStream in) + throws IOException, EnhancerUserException, EnhancerFatalError + { + OutputStream out =3D null; + try { + final File temp =3D File.createTempFile("enhancer", ".class"); + out =3D new BufferedOutputStream(new FileOutputStream(temp)); + + //enhance + final OutputStreamWrapper wrapper =3D new OutputStreamWrapper(= out); + final boolean enhanced =3D enhancer.enhanceClassFile(in, wrapp= er); + + closeOutputStream(out); + out =3D null; + createOutputFile(enhanced, + createClassFileName(wrapper.getClassName()), + temp); + } finally { + closeInputStream(in); + closeOutputStream(out); + } + } + + /** + * Enhances a zipfile. + * + * @param filename The filename of the zipfile. + */ + private void enhanceZipFile(String filename) + throws IOException, EnhancerUserException, EnhancerFatalError + { + ZipInputStream in =3D null; + ZipOutputStream out =3D null; + try { + final File temp =3D File.createTempFile("enhancer", ".zip"); + in =3D new ZipInputStream(new BufferedInputStream( + new FileInputStream(new File(filename)))); + out =3D new ZipOutputStream(new BufferedOutputStream( + new FileOutputStream(temp))); + + //enhance the zipfile + final boolean enhanced + =3D ClassFileEnhancerHelper.enhanceZipFile(enhancer, in, o= ut); + + //create the output file + closeOutputStream(out); + out =3D null; + createOutputFile(enhanced, new File(filename).getName(), temp); + } finally { + closeOutputStream(out); + closeInputStream(in); + } + } + + /** + * Opens an input stream for the given filename + * + * @param filename The name of the file. + * @return The input stream. + * @exception FileNotFoundException If the file could not be found. + */ + static private InputStream openFileInputStream(String filename) + throws FileNotFoundException + { + return new BufferedInputStream(new FileInputStream(new File(filename= ))); + } + + /** + * Opens an input stream for the given classname. The input stream is + * created via an URL that is obtained by the value of the sourcepath + * option and zip/jar file arguments. + *=20 + * @param classname The name of the class (dot-notation). + * @return The input stream. + * @exception IOException If an I/O error occured. + */ + private InputStream openClassInputStream(String classname) + throws IOException + { + final String resourcename =3D createClassFileName(classname); + return classLocator.getInputStreamForResource(resourcename); + } + + /** + * Creates a file object that represents the output zipfile for a giv= en + * zipfile to enhance. + * + * @param zipfilename The input zipfile name. + * @return The output zipfile name. + */ + private File createZipOutputFile(String zipfilename) + { + return new File(opts.destinationDirectory, + new File(zipfilename).getName()); + } + + /** + * Creates the output file for an enhaced class- or zipfile. If the + * enhanced file is written back depends on the command line options. + * + * @param enhanced Has the input file been enhanced? + * @param filename The name of the output file. + * @param temp The temp file, the output is written to. + * @exception IOException If the file could not be created. + */ + private void createOutputFile(boolean enhanced, + String filename, + File temp) + throws IOException + { + //noWrite or (not enhanced and not forceWrite) + if (opts.noWrite || (!enhanced && !opts.forceWrite)) { + temp.deleteOnExit(); + return; + } + + File file =3D new File(opts.destinationDirectory, filename); + createPathOfFile(file); + file.delete(); //delete old file if exists + boolean renamed =3D temp.renameTo(file); + if (!renamed) { + //@dave: empirical evidence shows that renameTo does not allow= for + // crossing filesystem boundaries. If it fails, try "by hand". + InputStream in =3D null; + OutputStream out =3D null; + try { + in =3D new FileInputStream(temp); + out =3D new FileOutputStream(file); + int PAGESIZE =3D 4096; // Suggest a better size? + byte data[] =3D new byte[PAGESIZE]; + while (in.available() > 0) { + int numRead =3D in.read(data, 0, PAGESIZE); + out.write(data, 0, numRead); + } + renamed =3D true; + } catch (IOException ex) { + throw new IOException("Could not rename temp file '" + + temp.getAbsolutePath() + + "' to '" + file.getAbsolutePath() + + "': " + ex); + } finally { + closeInputStream(in); + closeOutputStream(out); + } + if (renamed) { + temp.delete(); //delete temporary file + } + else { + throw new IOException("Could not rename temp file '" + + temp.getAbsolutePath() + + "' to '" + file.getAbsolutePath() + = "'."); + } + } + } + + /** + * Closes an input stream. + * + * @param in The input stream. + */ + private void closeInputStream(InputStream in) + { + if (in !=3D null) { + try { + in.close(); + } catch (IOException ex) { + printError(null, ex); + } + } + } + + /** + * Closes an output stream. + * + * @param out The output stream. + */ + private void closeOutputStream(OutputStream out) + { + if (out !=3D null) { + try { + out.close(); + } catch (IOException ex) { + printError(null, ex); + } + } + } + + /** + * Tests if a filename is a classfile name (by testing if the filename + * ends with ".class"). + * + * @param filename The name of the file. + * @return Do we have a potential classfile? + */ + static private boolean isClassFileName(String filename) + { + return filename.toLowerCase().endsWith(".class"); + } + + /** + * Tests if a filename is a zipfile (by testing if the filename + * ends with ".zip" or ".jar"). + * + * @param filename The name of the file. + */ + static private boolean isZipFileName(String filename) + { + final int n =3D filename.length(); + if (n < 5) { + return false; + } + final String ext =3D filename.substring(n - 4); + return ext.equalsIgnoreCase(".zip") || ext.equalsIgnoreCase(".jar"= ); + } + + /** + * Tests if a filename is a jdo file name (by testing if the filename + * ends with ".jdo"). + * + * @param filename The name of the file. + * @return Do we have a potential jdo file? + */ + static private boolean isJdoFileName(String filename) + { + return filename.toLowerCase().endsWith(".jdo"); + } + + /** + * Creates a filename from a classname. + * This is done by replacing '.' by '/'. + * + * @param classname The classname. + * @return The filename. + */ + static private String createClassFileName(String classname) + { + return classname.replace('.', '/') + ".class"; + } + + /** + * Creates only the path of the given file. + * + * @param file The file. + * @exception IOException If an error occured. + */ + static private void createPathOfFile(File file) + throws IOException + { + File dir =3D file.getAbsoluteFile().getParentFile(); + if (!dir.exists() && !dir.mkdirs()) { + throw new IOException("Error creating directory '" + + dir.getAbsolutePath() + "'."); + } + } + + // -------------------------------------------------------------------= --- + + /** + * Prints out an error. + * + * @param msg The error message (can be null). + * @param ex An optional exception (can be null). + */ + private void printError(String msg, + Throwable ex) + { + out.flush(); + if (msg !=3D null) { + err.println(msg); + } + if (ex !=3D null) { + if (opts.verbose) { + ex.printStackTrace(err); + } + else { + err.println(ex.toString()); + } + } + } + + /** + * Prints out a message. + * + * @param msg The message. + */ + private void printMessage(String msg) + { + out.println(msg); + } +} Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/package.ht= ml URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/enhancer/package.html?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/package.html = (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/enhancer/package.html = Fri Mar 18 17:02:29 2005 @@ -0,0 +1,26 @@ + + + + +Package org.apache.jdo.enhancer + + + + +

This package contains th eenhancer interface.

+ + Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Bundl= e=2Eproperties URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/impl/enhancer/Bundle.properties?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Bundle.p= roperties (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Bundle.p= roperties Fri Mar 18 17:02:29 2005 @@ -0,0 +1,220 @@ + + Copyright 2005 The Apache Software Foundation. +=20 + 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=20 +=20 + http://www.apache.org/licenses/LICENSE-2.0 +=20 + Unless required by applicable law or agreed to in writing, software=20 + distributed under the License is distributed on an "AS IS" BASIS,=20 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.=20 + See the License for the specific language governing permissions and=20 + limitations under the License. + + +# ResourceBundle properties file for model messages +# key consists of: enhancer.. +# - is optional, package under model +# - short description (use _ to represent space) +# all keys should be in lowercase + +# +# Global Enhancer Metadata messages +# + +# {0}=3Ddetail message +enhancer.metadata.message=3DJDO ENHANCER: Metadata: {0} + +# {0}=3Derror message +enhancer.metadata.error=3DJDO ENHANCER: Metadata Error: {0} + +# {0}=3Dwarning message +enhancer.metadata.warning=3DJDO ENHANCER: Metadata Warning: {0} + +# {0}=3Dmissing resource file +enhancer.metadata.cannot_read_resource=3DCannot read directory or jar file= : {0} + +# +# Detail Enhancer Metadata messages +# + +# {0}=3Dexception message +enhancer.metadata.jdomodel_error=3DA JDO model exception has occurred: {0} + +# {0}=3Dexception message +enhancer.metadata.io_error=3DAn I/O exception has occurred: {0} + +# {0}=3Dfilename +enhancer.metadata.using_properties=3Dusing properties file: {0} + +# {0}=3Dfilenames +enhancer.metadata.using_jdo_files=3Dusing jdo files: {0} + +# {0}=3Dpath +enhancer.metadata.using_jar_files=3Dusing jar/zip files: {0} + +# {0}=3Dpath +enhancer.metadata.using_source_path=3Dusing source path: {0} + +# {0}=3D +enhancer.metadata.using_no_metadata=3Dno JDO metadata source was specified + + +# +# Global enhancer messages +# + +# {0}=3Ddetailed message +enhancer.message=3DJDO ENHANCER: {0} + +# {0}=3Ddetailed message +enhancer.error=3DJDO ENHANCER: At least one error occurred while enhancing= input class for Transparent Persistence; detailed message(s): {0} + +# {0}=3Derror number, {1}=3Ddetailed message +enhancer.enumerated_error=3DJDO ENHANCER: Error ({0}): {1} + +# {0}=3Ddetailed message +enhancer.internal_error=3DJDO ENHANCER: An internal error occurred while e= nhancing input class; detailed message: {0} + +# {0}=3Ddetailed message +enhancer.warning=3DJDO ENHANCER: Warning: {0} + +# +# Enhancer core messages +# + +# +enhancer.class_format_error=3DI/O error while reading input stream or inpu= t stream does not denote a valid Java class. + +# +enhancer.io_error_while_writing_stream=3DI/O error while writing output st= ream. + +# {0}=3Ddir name +enhancer.unable_to_create_dir=3DUnable to create the directory named {0}. + +# {0}=3Dclass name +enhancer.class_previously_annotated=3DThe class {0} was previously annotat= ed. + +# {0}=3Dboolean +enhancer.class_implements_jdo_pc=3Dimplements the JDO PersistenceCapable i= nterface: {0}. + +# +enhancer.class_has_default_constructor=3Dhas default constructor. +enhancer.class_has_not_default_constructor=3Dhas not default constructor. + +# +enhancer.class_has_static_initializer=3Dhas static initializer. +enhancer.class_has_not_static_initializer=3Dhas not static initializer. + +# +enhancer.class_has_clone_method=3Dhas clone method. +enhancer.class_has_not_clone_method=3Dhas not clone method. + +# +enhancer.class_has_writeObject_method=3Dhas writeObject method. +enhancer.class_has_not_writeObject_method=3Dhas not writeObject method. + +# +enhancer.class_has_writeReplace_method=3Dhas writeReplace method. +enhancer.class_has_not_writeReplace_method=3Dhas not writeReplace method. + +# +enhancer.class_has_readObject_method=3Dhas readObject method. +enhancer.class_has_not_readObject_method=3Dhas not readObject method. + +# {0}=3Dclass name +enhancer.class_missing_default_constructor=3DThe persistence-capable class= {0} does not provide a default (no-argument) constructor. + +# {0}=3Dboolean +enhancer.class_has_generic_jdo_fields=3Dhas the generic JDO fields: {0}. + +# {0}=3Dboolean +enhancer.class_has_generic_jdo_methods=3Dhas the generic JDO methods: {0}. + +# {0}=3Dboolean +enhancer.class_has_generic_jdo_members=3Dhas the generic JDO fields and me= thods: {0}. + +# {0}=3Dboolean +enhancer.class_has_specific_jdo_fields=3Dhas the specific JDO fields: {0}. + +# {0}=3Dboolean +enhancer.class_has_specific_jdo_methods=3Dhas the specific JDO methods: {0= }=2E + +# {0}=3Dboolean +enhancer.class_has_specific_jdo_members=3Dhas the specific JDO fields and = methods: {0}. + +# {0}=3Dboolean +enhancer.class_has_oid_handling_jdo_methods=3Dhas the ObjectId-handling JD= O methods: {0}. + +# {0}=3Dboolean +enhancer.class_has_callback_jdo_methods=3Dhas the instance-callback JDO me= thods: {0}. + +# {0}=3Dclass name, {1}=3Dmethod name +enhancer.class_defines_jdo_method=3DThe persistence-capable class {0} defi= nes a JDO method called {1}. + +# {0}=3Dclass name, {1}=3Dfield name +enhancer.class_defines_jdo_field=3DThe persistence-capable class {0} defin= es a JDO field called {1}. + +# {0}=3Dclass name, {1}=3Dmember name +enhancer.class_has_jdo_like_member=3DThe persistence-capable class {0} def= ines a member {1} whose name starts with the reserved jdo prefix. + +# {0}=3Dclass name, {1}=3Dmethod name, +# {2}=3Dexpected signature, {3}=3Dfound signature +# {4}=3Dexpected modifiers, {5}=3Dfound modifiers +enhancer.class_has_illegally_declared_jdo_member=3DThe persistence-capable= class {0} has an illegally declared JDO member: {1}; expected signature: '= '{2}''; found signature: ''{3}''; expected access modifier flags: {4}; foun= d access modifier flags: {5}. + +# {0}=3Dclass name, {1}=3Dfound method names, {2}=3Dmissing method names +enhancer.class_has_inconsistently_declared_jdo_members=3DThe persistence-c= apable class {0} has an incosistent set of declared JDO members; found: {1}= ; missing: {2}. + +# +# Other Enhancer messages +# + +# {0}=3Dfilenames +enhancer.using_jdo_files=3Dusing jdo files: {0} + +# {0}=3Dpath +enhancer.using_archive_files=3Dusing jar/zip files: {0} + +# {0}=3Dpath +enhancer.using_source_path=3Dusing source path: {0} + +# {0}=3Dresource file name +enhancer.using_file=3Dusing file: {0} + +# {0}=3Dresource path element +enhancer.using_path_element=3Dusing path element: {0} + +# {0}=3Dclass name, {1}=3Dfile name, {2}=3Dfile name +enhancer.class_already_entered=3DThe class {0} from {1} is already entered= from {2}. + +# {0}=3Ddir name, {1}=3Ddir name +enhancer.destination_directory_already_set=3DAttempt to set the destinatio= n directory to {0}, but it has already been set to {1}. + +# {0}=3Ddir name +enhancer.destination_directory_not_exist=3DThe destination directory {0} d= oes not exist. + +# {0}=3Dresource name +enhancer.found_resource=3Dfound resource: {0} +enhancer.not_found_resource=3Dnot found resource: {0} + +# {0}=3Dresource name +enhancer.cannot_read_resource=3Dresource does not exist or cannot be read:= {0} + +# {0}=3Dresource name {1}=3Dexception message +enhancer.io_error_while_reading_resource=3DAn I/O exception has occurred w= hile reading resource: {0}, exception: {1} + +# {0}=3Dresource name +enhancer.io_error_while_reading_resource=3DAn I/O exception has occurred: = {0} + +# {0}=3Dresource name +enhancer.illegal_path_element=3Dillegal element source path: {0} + +# +# Enhancer exception messages +# + +MSG_CauseThrowable=3DCauseThrowable: +MSG_CauseThrowableStackTrace=3DCauseThrowableStackTrace: Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Class= ArgMain.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/impl/enhancer/ClassArgMain.java?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArg= Main.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArg= Main.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,180 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * 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=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * 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 =3D options; + } + + // -------------------------------------------------------------------= --- + + /** + * Initializes the class locator. + */ + protected void initClassLocator() + throws IOException + { + // create resource locator for specified source path + final String path =3D options.sourcePath.value; + if (path !=3D null) { + affirm(path.length() > 0); + final boolean verbose =3D options.verbose.value; + classes =3D new PathResourceLocator(out, verbose, path); + } + } + + /** + * Initializes all components. + */ + protected void init() + throws EnhancerFatalError, EnhancerUserException + { + try { + initClassLocator(); + } catch (Exception ex) { + throw new EnhancerFatalError(ex); + } + } + =20 + // -------------------------------------------------------------------= --- + + /** + * Returns the file name for a class name. + * This is done by replacing '.' by '/'. + * + * @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 !=3D 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. + *=20 + * @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 !=3D null); + final String resName =3D className.replace('.', '/') + ".class"; + //^olsen: support for timing + //if (options.doTiming.value) {...} + final InputStream s =3D classes.getInputStreamForResource(resName); + affirm(s !=3D null); + return new BufferedInputStream(s); + } + + /** + * Closes an input stream. + * + * @param in the input stream + */ + protected void closeInputStream(InputStream in) + { + if (in !=3D null) { + try { + in.close(); + } catch (IOException ex) { + printlnErr("", ex); + } + } + } + + // -------------------------------------------------------------------= --- + + /** + * Runs this class + */ + static public void main(String[] args) + { + final PrintWriter out =3D new PrintWriter(System.out, true); + out.println("--> ClassArgMain.main()"); + final ClassArgMain main =3D new ClassArgMain(out, out); + int res =3D main.run(args); + out.println("<-- ClassArgMain.main(): exit =3D " + res); + System.exit(res); + } +} Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Class= ArgOptions.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/impl/enhancer/ClassArgOptions.java?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArg= Options.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassArg= Options.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,220 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * 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=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * 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 ".class" (ignoring case= )=2E + * + * @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 ".jar" or + * ".zip" (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 =3D filename.toLowerCase(); + return (s.endsWith(".jar") || s.endsWith(".zip")); + } + + // -------------------------------------------------------------------= --- + + /** + * The source path option. + */ + public final StringOption sourcePath + =3D createStringOption("sourcepath", "s", + " : path for lookup of class files"); + + /** + * The list of class name arguments. + */ + public final List classNames =3D new ArrayList(); =20 + + /** + * The list of class file name arguments. + */ + public final List classFileNames =3D new ArrayList(); =20 + + /** + * The list of archive file name arguments. + */ + public final List archiveFileNames =3D new ArrayList(); =20 + + /** + * Creates an instance. + */ + public ClassArgOptions(PrintWriter out, + PrintWriter err)=20 + { + super(out, err); + } + + // -------------------------------------------------------------------= --- + + /** + * Print a usage message to System.err. + */ + public void printUsageHeader() + { + printlnErr("Usage: .. .."); + printlnErr(indent + + "-s .."); + printlnErr(indent + + " .."); + //^olsen: re-enable support for archive files + //printlnErr(indent + // + " .."); + } + + /** + * Print a usage message to System.err. + */ + public void printArgumentUsage() + { + printlnErr(indent + + " the fully qualified name of a Java= class"); + printlnErr(indent + + " the name of a .class file"); + printlnErr(indent + + " 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); + } + =20 + /** + * Print argument of list type. + */ + public void printListArgument(String name, List list) + { + print(indent); + final StringBuffer s =3D new StringBuffer(); + for (Iterator i =3D list.iterator(); i.hasNext();) { + s.append(" " + i.next()); + } + println(name + " =3D {" + s.toString() + " }"); + println(); + } + + /** + * Check options and arguments. + */ + public int check() + { + int res; + if ((res =3D super.check()) !=3D OK) { + return res; + } + + // group input file arguments + for (Iterator names =3D arguments.iterator(); names.hasNext();) { + final String name =3D (String)names.next(); + if (isClassFileName(name)) { + classFileNames.add(name); + } else if (isArchiveFileName(name)) { + archiveFileNames.add(name); + } else { + classNames.add(name); + } + } + + if (verbose.value) { + printAll(); + } + =20 + // check class arguments + final int argTypes =3D ((classNames.isEmpty() ? 0 : 1) + + (classFileNames.isEmpty() ? 0 : 1) + + (archiveFileNames.isEmpty() ? 0 : 1)); + if (argTypes =3D=3D 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 eit= her class name, class file, or archive file"); + return USAGE_ERROR; + } + =20 + // check sourcepath option + if (sourcePath.value =3D=3D null && !classNames.isEmpty()) { + printUsageError("No source-path specified for lookup of classe= s"); + return USAGE_ERROR; + } + if (sourcePath.value !=3D 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 di= sabled"); + return USAGE_ERROR; + } + + return OK; + } + + // -------------------------------------------------------------------= --- + + /** + * Tests the class. + */ + static public void main(String[] args) + { + final PrintWriter out =3D new PrintWriter(System.out, true); + out.println("--> ClassArgOptions.main()"); + final ClassArgOptions options =3D new ClassArgOptions(out, out); + out.println(" options.process() ..."); + int res =3D options.process(args); + out.println(" return value: " + res); + out.println("<-- ClassArgOptions.main()"); + } +} Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Class= FileEnhancer.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/impl/enhancer/ClassFileEnhancer.java?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFil= eEnhancer.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFil= eEnhancer.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,65 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * 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=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * 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 true if the class has been enhanced, + * false 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. + *

+ * 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 true if the class has been enhanced, + * false otherwise. + */ + boolean enhanceClassFile(InputStream in, + OutputStreamWrapper out) + throws EnhancerUserException, EnhancerFatalError; +} Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Class= FileEnhancerHelper.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/impl/enhancer/ClassFileEnhancerHelper.java?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFil= eEnhancerHelper.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFil= eEnhancerHelper.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,204 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * 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=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * 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=C3=ADon (if any) as the in= put + * stream. + * + * @param enhancer The enhancer. + * @param zip_in The zip input stream. + * @param zip_out The zip output stream. + * + * @return true if at least one entry of the zip file h= as + * been enhanced, false 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 =3D false; + try { + CRC32 crc32 =3D new CRC32(); + ZipEntry entry; + while ((entry =3D zip_in.getNextEntry()) !=3D null) { + InputStream in =3D zip_in; + final ZipEntry out_entry =3D 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 =3D openZipEntry(zip_in); + in.mark(Integer.MAX_VALUE); + final ByteArrayOutputStream tmp + =3D new ByteArrayOutputStream(); + if (enhancer.enhanceClassFile(in, tmp)) { + enhanced =3D true; + final byte[] bytes =3D tmp.toByteArray(); + tmp.close(); + in.close(); + modifyZipEntry(out_entry, bytes, crc32); + in =3D 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 !=3D 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 =3D in.read()) > -1) { + out.write(b); + } + } + + /** + * Opens the next zip entry of a zip input stream and copies it to + * a java.io.ByteArrayOutputStream. It's byte array is m= ade + * available via an java.io.ByteArrayInputStream 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 =3D 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 wo= n't + * be compressed). + * + * @param entry The zip entry to modify. + * @param bytes The uncompressed byte representation of the classfi= le. + * @param crc32 The checksum evaluator. + */ + private static void modifyZipEntry(ZipEntry entry, + byte [] bytes, + CRC32 crc32) + { + entry.setSize(bytes.length); + if (entry.getMethod() =3D=3D 0) { + //no compression (ZipInputStream.STORED - not accessible) + crc32.reset(); + crc32.update(bytes); + entry.setCrc(crc32.getValue()); + entry.setCompressedSize(bytes.length); + } + } + + /** + * Determines if a given entry represents a classfile. + * + * @return Does the given entry represent a classfile? + */ + private static boolean isClassFileEntry(ZipEntry entry) + { + return entry.getName().endsWith(".class"); + } +} Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/Class= FileEnhancerTimer.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/impl/enhancer/ClassFileEnhancerTimer.java?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFil= eEnhancerTimer.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/enhancer/ClassFil= eEnhancerTimer.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,70 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * 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=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * 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 =3D delegate; + } + + public boolean enhanceClassFile(InputStream inClassFile, + OutputStream outClassFile) + throws EnhancerUserException, EnhancerFatalError + { + try { + timer.push("ClassFileEnhancer.enhanceClassFile(InputStream,Out= putStream)"); + return delegate.enhanceClassFile(inClassFile, outClassFile); + } finally { + timer.pop(); + } + } + + public boolean enhanceClassFile(InputStream inClassFile, + OutputStreamWrapper outClassFile) + throws EnhancerUserException, EnhancerFatalError + { + try { + timer.push("ClassFileEnhancer.enhanceClassFile(InputStream,Out= putStreamWrapper)"); + return delegate.enhanceClassFile(inClassFile, outClassFile); + } finally { + timer.pop(); + } + } +}