| /* |
| * 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(); |
| } |
| } |
| } |