jkesselm    00/10/26 15:00:53

  Modified:    java/src/org/apache/xalan/utils/synthetic JavaUtils.java
  Log:
  Generalizing, esp. to deal with MSVJ++
  
  Revision  Changes    Path
  1.2       +216 -66   
xml-xalan/java/src/org/apache/xalan/utils/synthetic/JavaUtils.java
  
  Index: JavaUtils.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/utils/synthetic/JavaUtils.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- JavaUtils.java    2000/10/13 02:33:14     1.1
  +++ JavaUtils.java    2000/10/26 22:00:52     1.2
  @@ -1,79 +1,229 @@
  -/* $Id: JavaUtils.java,v 1.1 2000/10/13 02:33:14 sboag Exp $ */
  +/*
  + * The Apache Software License, Version 1.1 
  + *
  + *
  + * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * reserved.
  + *
  + * Redistribution and use in source and binary forms, with or without
  + * modification, are permitted provided that the following conditions
  + * are met:
  + *
  + * 1. Redistributions of source code must retain the above copyright
  + *    notice, this list of conditions and the following disclaimer. 
  + *
  + * 2. Redistributions in binary form must reproduce the above copyright
  + *    notice, this list of conditions and the following disclaimer in
  + *    the documentation and/or other materials provided with the
  + *    distribution.
  + *
  + * 3. The end-user documentation included with the redistribution,
  + *    if any, must include the following acknowledgment:  
  + *       "This product includes software developed by the
  + *        Apache Software Foundation (http://www.apache.org/)."
  + *    Alternately, this acknowledgment may appear in the software itself,
  + *    if and wherever such third-party acknowledgments normally appear.
  + *
  + * 4. The names "Xalan" and "Apache Software Foundation" must
  + *    not be used to endorse or promote products derived from this
  + *    software without prior written permission. For written 
  + *    permission, please contact [EMAIL PROTECTED]
  + *
  + * 5. Products derived from this software may not be called "Apache",
  + *    nor may "Apache" appear in their name, without prior written
  + *    permission of the Apache Software Foundation.
  + *
  + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  + * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  + * SUCH DAMAGE.
  + * ====================================================================
  + *
  + * This software consists of voluntary contributions made by many
  + * individuals on behalf of the Apache Software Foundation and was
  + * originally based on software copyright (c) 1999, Lotus
  + * Development Corporation., http://www.lotus.com.  For more
  + * information on the Apache Software Foundation, please see
  + * <http://www.apache.org/>. 
  + *
  + * $Id: JavaUtils.java,v 1.2 2000/10/26 22:00:52 jkesselm Exp $ 
  + */
   
   package org.apache.xalan.utils.synthetic;
   
   import java.io.IOException;
   
  +/** This class supports invoking Java compilation from within
  + * a Java program. Recent versions of the Java environment have
  + * provided such an API (in tools.jar). But that isn't available
  + * on all platforms, and a fallback to the command line may be needed
  + * (though this too may not always be available, eg. for security
  + * reasons).
  + * <p>
  + * There's an additional complication in some environments --
  + * such as Microsoft's VJ++ -- where the classpath as seen in
  + * the System Properties may not be the one the user expects.
  + * The code here is parameterized to try to deal with that.
  + */
   public class JavaUtils
   {
  -  // Debug flag - generates debug stuff if true.
  -  private static boolean debug = false;
  +     // One-time flag for whether we could dynamically load compiler API
  +     private static boolean cantLoadCompiler=false; 
   
  -  // Temporarily copied from JavaEngine...
  -  private static boolean cantLoadCompiler=false; // One-time flag for 
following
  -
  -  // ADDED BY JKESS; callers want control over the -g option.
  -  public static void setDebug(boolean newDebug)
  -  {
  -    debug=newDebug;
  -  }
  -
  -  public static boolean JDKcompile(String fileName, String classPath)
  -  {
  -    if (debug)
  -    {
  -      System.err.println ("JavaEngine: Compiling " + fileName);
  -      System.err.println ("JavaEngine: Classpath is " + classPath);
  -    }
  +     // Debug flag - generates debug stuff if true.
  +     private static boolean debug = false;
  +  
  +     /** Control whether compilation occurs with the -g option
  +      * (debugging information included in generated classfile).
  +      * This is an attribute, rather than a parameter on the compile
  +      * method, largely because it tends to be an all-or-nothing decision; 
  +      * generally you're either doing program development and want it,
  +      * or running in production mode and don't. But that may not match
  +      * the needs of future users...
  +      * <p>
  +      * TODO: Consider whether debug should be a parameter.
  +      * 
  +      * @param boolean newDebug True to request debugging data,
  +      * false to request optimized output. (It's uncommon to
  +      * want both or neither!)
  +      */ 
  +     public static void setDebug(boolean newDebug)
  +     {
  +         debug=newDebug;
  +     }
  +
  +     /** Try to compile a .java file on disk. This will first attempt to
  +      * use the sun.java.tools.javac() method, then (if that is unavailable)
  +      * fall back upon shelling out to a command line and running javac
  +      * there.
  +      * <p>
  +      * NOTE: This must be _compiled_ with sun.java.tools.* (tools.jar)
  +      * available. We could change that to use reflection instead, if we
  +      * accept some overhead... minor compared to the cost of running the
  +      * compiler!
  +      * <p>
  +      * This has complications on some platforms. For example, under 
  +      * Microsoft Visual Java ++ (at least, as installed on my test system),
  +      * I found that I had to specify paths to both javac and xerces.jar
  +      * rather than counting on the shell's path and classpath having
  +      * been set to reach these. For that reason I've parameterized this
  +      * method with a few system properties, so you can adapt it to your
  +      * own system's needs without modifying the code:
  +      * <dl>
  +      * <dt>org.apache.xalan.utils.synthetic.javac
  +      * <dd>Command line issued to invoke the compiler. Defaults to "javac",
  +      * which should work in most systems. In VJ++, try setting it to
  +      * "cmd /c %JAVA_HOME%\\bin\javac.exe"
  +      * <dt>org.apache.xalan.utils.synthetic.moreclasspath
  +      * <dd>Additional classpath, to be prepended to the one retrieved from
  +      * java.class.path. Defaults to "" (empty). In VJ++, try setting it to
  +      * point to your copy of xerces.jar, which may not be found otherwise.
  +      * TODO: Reconsider prepend versus append!
  +      * </dl>
  +      * 
  +      * @param String fileName Which .java file to compile. Note that this 
may
  +      * be relative to the "current directory".
  +      * @param String classPath Additional places to look for classes that
  +      * this .java file depends upon. Becomes the javac command's
  +      * -classpath parameter value.
  +      * @return boolean True iff compilation succeeded.
  +      */
  +     public static boolean JDKcompile(String fileName, String classPath)
  +     {
  +             String moreClassPath=
  +                     
System.getProperty("org.apache.xalan.util.synthetic.moreclasspath","")
  +                     .trim();
  +             if(moreClassPath.length()>0)
  +                     classPath=moreClassPath+';'+classPath;
  +                                                                             
                  
  +             if (debug)
  +             {
  +                     System.err.println ("JavaEngine: Compiling " + 
fileName);
  +                     System.err.println ("JavaEngine: Classpath is " + 
classPath);
  +             }
       
  -    String option = debug ? "-g" : "-O";
  +             String code_option = debug ? "-g" : "-O";
   
  -    if(!cantLoadCompiler)
  -      {
  -  String args[] = {
  -    option,
  -    "-classpath",
  -    classPath,
  -    fileName
  -  };
  -  try
  -    {
  -      return new sun.tools.javac.Main(System.err, "javac").compile(args);
  -    }
  -  catch (Throwable th)
  -    {
  -      System.err.println("WARNING: Unable to load Java 1.1 compiler.");
  -      System.err.println("\tSwitching to command-line invocation.");
  -      cantLoadCompiler=true;
  -    }
  -      }
  +             // Start by trying Sun's compiler API
  +         if(!cantLoadCompiler)
  +             {
  +                     String args[] = {
  +                             code_option,
  +                         "-classpath", classPath,
  +                             fileName
  +                     };
  +                             
  +                     try
  +                 {
  +                             return new sun.tools.javac.Main(System.err, 
"javac").compile(args);
  +                     }
  +                     catch (Throwable th)
  +                     {
  +                             System.err.println("WARNING: Unable to load 
Java 1.1 compiler.");
  +                             System.err.println("\tSwitching to command-line 
invocation.");
  +                             cantLoadCompiler=true;
  +                     }
  +             }
       
  -    // Can't load javac; try exec'ing it.
  -    String args[] = {
  -      "javac",
  -      option,
  -      "-classpath",
  -      classPath,
  -      fileName
  -    };
  -    try
  -      {
  -  Process p=java.lang.Runtime.getRuntime().exec(args);
  -  p.waitFor();
  -  return(p.exitValue()!=0);
  -      }
  -    catch(IOException e)
  -      {
  -  System.err.println("ERROR: IO exception during exec(javac).");
  -      }
  -    catch(SecurityException e)
  -      {
  -  System.err.println("ERROR: Unable to create subprocess to exec(javac).");
  -      }
  -    catch(InterruptedException e)
  -      {
  -  System.err.println("ERROR: Wait for exec(javac) was interrupted.");
  -      }
  -    return false;
  +             // FALLTHRU:
  +             // Can't load javac() method; try shelling out to the command
  +             // line and invoking it via exec(). 
  +             String javac_command=
  +                     
System.getProperty("org.apache.xalan.util.synthetic.javac","javac");
  +         String args[] = {
  +                     javac_command,
  +                     code_option,
  +                     "-classpath", classPath,
  +                     fileName
  +                     };
  +             try
  +             {
  +                     Process p=java.lang.Runtime.getRuntime().exec(args);
  +                     int compileOK=waitHardFor(p); // pause for debugging...
  +                     return compileOK==0; //0 == no error reported
  +             }
  +             catch(IOException e)
  +             {
  +                     System.err.println("ERROR: IO exception during 
exec(javac).");
  +             }
  +             catch(SecurityException e)
  +             {
  +                     System.err.println("ERROR: Unable to create subprocess 
to exec(javac).");
  +             }
  +             
  +             // FALLTHRU: All attempts failed.
  +             return false;
  +     }
  +
  +  /** Subroutine: Like p.waitFor, but discards the InterruptedException
  +   * and goes right back into a wait. I don't want to report compiler
  +   * success or failure until it really has succeeded or failed... I think.
  +   * @param Process p to be waited for
  +   * @return the exitValue() of the process.
  +   */
  +  static int waitHardFor(java.lang.Process p)
  +  {
  +    boolean done=false;
  +    while(!done)
  +        try
  +        {
  +            p.waitFor();
  +            done=true;
  +        }
  +        catch(InterruptedException e)
  +        {
  +            System.err.println("(Compiler process wait interrupted and 
resumed)");
  +        }
  +     int ev=p.exitValue();  // Pause for debugging...
  +     return ev;
     }
  +     
   }
  
  
  

Reply via email to