blob: 0ac737075cc210f8830424e6f82a3c8f27d93119 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2003 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 "Apache" 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 apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache
* XMLBeans", 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) 2000-2003 BEA Systems
* Inc., <http://www.bea.com/>. For more information on the Apache Software
* Foundation, please see <http://www.apache.org/>.
*/
package org.apache.xmlbeans.impl.tool;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.Arrays;
import java.io.File;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileFilter;
import java.io.FileWriter;
import java.net.URI;
import java.net.URISyntaxException;
public class CodeGenUtil
{
public static String DEFAULT_MEM_START = "8m";
public static String DEFAULT_MEM_MAX = "256m";
public static String DEFAULT_COMPILER = "javac";
public static String DEFAULT_JAR = "jar";
//workaround for Sun bug # 4723726
public static URI resolve(URI base, URI child)
{
URI ruri = base.resolve(child);
//fix up normalization bug
if ("file".equals(ruri.getScheme()) && ! child.equals(ruri))
{
if (base.getPath().startsWith("//") && !ruri.getPath().startsWith("//"))
{
String path = "///".concat(ruri.getPath());
try
{
ruri = new URI("file", null, path, ruri.getQuery(), ruri.getFragment());
}
catch(URISyntaxException uris)
{}
}
}
return ruri;
}
static void addAllJavaFiles(List srcFiles, List args)
{
for (Iterator i = srcFiles.iterator(); i.hasNext(); )
{
File f = (File)i.next();
if (!f.isDirectory())
{
args.add(quoteAndEscapeFilename(f.getAbsolutePath()));
}
else
{
List inside = (Arrays.asList(f.listFiles(
new FileFilter()
{
public boolean accept(File file)
{ return (file.isFile() && file.getName().endsWith(".java")) || file.isDirectory(); }
}
)));
addAllJavaFiles(inside, args);
}
}
}
static private String quoteAndEscapeFilename(String filename)
{
// don't quote if there's no space
if (filename.indexOf(" ") < 0)
return filename;
// bizarre. javac expects backslash escaping if we quote the classpath
// bizarre also. replaceAll expects replacement backslashes to be double escaped.
return "\"" + filename.replaceAll("\\\\", "\\\\\\\\") + "\"";
}
static private String quoteNoEscapeFilename(String filename)
{
// don't quote if there's no space, and don't quote on linux
if (filename.indexOf(" ") < 0 || File.separatorChar == '/')
return filename;
return "\"" + filename + "\"";
}
/**
* Invokes javac on the generated source files in order to turn them
* into binary files in the output directory. This will return a list of
* <code>GenFile</code>s for all of the classes produced or null if an
* error occurred.
*
* @deprecated
*/
static public boolean externalCompile(List srcFiles, File outdir, File[] cp, boolean debug)
{
return externalCompile(srcFiles, outdir, cp, debug, DEFAULT_COMPILER, DEFAULT_MEM_START, DEFAULT_MEM_MAX, false, false);
}
/**
* Invokes javac on the generated source files in order to turn them
* into binary files in the output directory. This will return a list of
* <code>GenFile</code>s for all of the classes produced or null if an
* error occurred.
*/
static public boolean externalCompile(List srcFiles, File outdir, File[] cp, boolean debug, String javacPath, String memStart, String memMax, boolean quiet, boolean verbose)
{
List args = new ArrayList();
File javac = findJavaTool(javacPath == null ? DEFAULT_COMPILER : javacPath);
assert (javac.exists()) : "compiler not found " + javac;
args.add(javac.getAbsolutePath());
if (outdir == null)
{
outdir = new File(".");
}
else
{
args.add("-d");
args.add(quoteAndEscapeFilename(outdir.getAbsolutePath()));
}
if (cp == null)
{
cp = systemClasspath();
}
if (cp.length > 0)
{
StringBuffer classPath = new StringBuffer();
// Add the output directory to the classpath. We do this so that
// javac will be able to find classes that were compiled
// previously but are not in the list of sources this time.
classPath.append(outdir.getAbsolutePath());
// Add everything on our classpath.
for (int i = 0; i < cp.length; i++)
{
classPath.append(File.pathSeparator);
classPath.append(cp[i].getAbsolutePath());
}
args.add("-classpath");
// bizarre. javac expects backslash escaping if we quote the classpath
args.add(quoteAndEscapeFilename(classPath.toString()));
}
args.add("-source");
args.add("1.4");
args.add(debug ? "-g" : "-g:none");
if (verbose)
args.add("-verbose");
addAllJavaFiles(srcFiles, args);
File clFile = null;
try
{
clFile = File.createTempFile("javac", "");
FileWriter fw = new FileWriter(clFile);
Iterator i = args.iterator();
for (i.next(); i.hasNext();)
{
String arg = (String)i.next();
fw.write(arg);
fw.write('\n');
}
fw.close();
List newargs = new ArrayList();
newargs.add(args.get(0));
if (memStart != null && memStart.length() != 0)
newargs.add("-J-Xms" + memStart);
if (memMax != null && memMax.length() != 0)
newargs.add("-J-Xmx" + memMax);
newargs.add("@" + clFile.getAbsolutePath());
args = newargs;
}
catch (Exception e)
{
System.err.println("Could not create command-line file for javac");
}
try
{
String[] strArgs = (String[]) args.toArray(new String[args.size()]);
if (verbose)
{
System.out.print("compile command:");
for (int i = 0; i < strArgs.length; i++)
System.out.print(" " + strArgs[i]);
System.out.println();
}
final Process proc = Runtime.getRuntime().exec(strArgs);
StringBuffer errorBuffer = new StringBuffer();
StringBuffer outputBuffer = new StringBuffer();
ThreadedReader out = new ThreadedReader(proc.getInputStream(), outputBuffer);
ThreadedReader err = new ThreadedReader(proc.getErrorStream(), errorBuffer);
proc.waitFor();
if (verbose || proc.exitValue() != 0)
{
if (outputBuffer.length() > 0) {
System.out.println(outputBuffer.toString());
System.out.flush();
}
if (errorBuffer.length() > 0) {
System.err.println(errorBuffer.toString());
System.err.flush();
}
if (proc.exitValue() != 0)
return false;
}
}
catch (Throwable e)
{
System.err.println(e.toString());
System.err.println(e.getCause());
e.printStackTrace(System.err);
return false;
}
if (clFile != null)
clFile.delete();
return true;
}
public static File[] systemClasspath()
{
List cp = new ArrayList();
String[] systemcp = System.getProperty("java.class.path").split(File.pathSeparator);
for (int i = 0; i < systemcp.length; i++)
{
cp.add(new File(systemcp[i]));
}
return (File[])cp.toArray(new File[cp.size()]);
}
static public boolean externalJar(File srcdir, File outfile)
{
return externalJar(srcdir, outfile, DEFAULT_JAR, false, false);
}
static public boolean externalJar(File srcdir, File outfile, String jarPath, boolean quiet, boolean verbose)
{
List args = new ArrayList();
File jar = findJavaTool(jarPath == null ? DEFAULT_JAR : jarPath);
assert (jar.exists()) : "jar not found " + jar;
args.add(jar.getAbsolutePath());
args.add("cf" + (verbose ? "v" : ""));
args.add(quoteNoEscapeFilename(outfile.getAbsolutePath()));
args.add("-C");
args.add(quoteNoEscapeFilename(srcdir.getAbsolutePath()));
args.add(".");
try
{
String[] strArgs = (String[]) args.toArray(new String[args.size()]);
if (verbose)
{
System.out.print("jar command:");
for (int i = 0; i < strArgs.length; i++)
System.out.print(" " + strArgs[i]);
System.out.println();
}
final Process proc = Runtime.getRuntime().exec(strArgs);
StringBuffer errorBuffer = new StringBuffer();
StringBuffer outputBuffer = new StringBuffer();
ThreadedReader out = new ThreadedReader(proc.getInputStream(), outputBuffer);
ThreadedReader err = new ThreadedReader(proc.getErrorStream(), errorBuffer);
proc.waitFor();
if (verbose || proc.exitValue() != 0)
{
if (outputBuffer.length() > 0) {
System.out.println(outputBuffer.toString());
System.out.flush();
}
if (errorBuffer.length() > 0) {
System.err.println(errorBuffer.toString());
System.err.flush();
}
if (proc.exitValue() != 0)
return false;
}
}
catch (Throwable e)
{
e.printStackTrace(System.err);
return false;
}
return true;
}
/**
* Look for tool in current directory and ${JAVA_HOME}/../bin and
* try with .exe file extension.
*/
private static File findJavaTool(String tool)
{
File toolFile = new File(tool);
if (toolFile.isFile()) {
return toolFile;
}
File result = new File(tool + ".exe");
if (result.isFile()) {
return result;
}
String home = System.getProperty("java.home");
String sep = File.separator;
result = new File(home + sep + ".." + sep + "bin", tool);
if (result.isFile()) {
return result;
}
result = new File(result.getPath() + ".exe");
if (result.isFile()) {
return result;
}
result = new File(home + sep + "bin", tool);
if (result.isFile()) {
return result;
}
result = new File(result.getPath() + ".exe");
if (result.isFile()) {
return result;
}
// just return the original toolFile and hope that it is on the PATH.
return toolFile;
}
/**
* Reads the given input stream into the given buffer until there is
* nothing left to read.
*/
static private class ThreadedReader
{
public ThreadedReader(InputStream stream, final StringBuffer output)
{
final BufferedReader reader =
new BufferedReader(new InputStreamReader(stream));
Thread readerThread = new Thread(new Runnable() {
public void run()
{
String s;
try
{
while ((s = reader.readLine()) != null)
output.append(s + "\n");
}
catch (Exception e)
{}
}
});
readerThread.start();
}
}
}