001 // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org)
002 // The Molly framework is freely distributable under the terms of an
003 // MIT-style license. For details, see the molly pages web site at:
004 // http://www.mollypages.org/. Use, modify, have fun !
005
006 package fc.util.pagetemplate;
007
008 import java.io.*;
009 import java.util.*;
010 import fc.util.*;
011
012 /**
013 Used to compile generated pages by invoking the java compiler.
014 */
015 public class TemplateCompiler
016 {
017 private static final boolean dbg = false;
018
019 String error;
020 File javafile;
021 String classpath;
022
023 /**
024 Creates a new page compiler that will use the default (system) classpath
025 as seen by 'javac' when it is invoked from the command line. No
026 seperate "encoding" flag will be specified to the javac.
027
028 */
029 public TemplateCompiler(File javafile)
030 {
031 this.javafile = javafile;
032 }
033
034 /**
035 Creates a new page compiler with the specified classpath. This is useful
036 when the classpath must contain some directories within the servlet web
037 application, just as <tt>WEB-INF/classes</tt>, <tt>WEB-INF/lib</tt> etc.
038
039 @param javafile the source java file to compile
040 @param classpath classpath to use when compiling
041 */
042 public TemplateCompiler(File javafile, String classpath)
043 {
044 this.javafile = javafile;
045 this.classpath = classpath;
046 }
047
048 public String getError()
049 {
050 return error;
051 }
052
053 public boolean compile() throws IOException
054 {
055 //javac 1.5.x does not crap out if a 0 byte source file is fed to it
056 //it simply returns 0 (implying success) but does NOT generate a classfile. so this hack.
057 if (javafile.length() == 0)
058 {
059 error = "Java source file [" +
060 javafile.getCanonicalPath() +
061 "] size was 0 bytes. This file cannot be compiled";
062
063 return false;
064 }
065
066 //this is ok too: {"bash", "-c", "javac -nowarn /tmp/c.java"});
067 List javac_cmd = new ArrayList();
068 javac_cmd.add("javac");
069 javac_cmd.add("-nowarn");
070
071 javac_cmd.add("-encoding");
072 javac_cmd.add(TemplatePage.DEFAULT_ENCODING);
073
074 if (classpath != null) {
075 javac_cmd.add("-classpath");
076 javac_cmd.add(classpath);
077 }
078 javac_cmd.add(javafile.getCanonicalPath());
079
080 if (dbg) System.out.println("Compile command: " + javac_cmd);
081
082 ProcessBuilder pb = new ProcessBuilder(javac_cmd);
083
084 Process p = pb.start();
085
086 int exit_val = 0;
087
088 /*
089 have to read out/err from the process otherwise it may hang if
090 javac has lots of output (in case of errors)...waitFor will not
091 return since the process is hung.
092 See: jdk 1.5 docs and
093 http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
094
095 try
096 {
097 exit_val = p.waitFor();
098 }
099 catch (InterruptedException e)
100 {
101 throw new IOException(e.toString());
102 }
103 */
104
105 CharArrayWriter buf = new CharArrayWriter(1024);
106
107 InputStream stderr = new BufferedInputStream(p.getErrorStream());
108 InputStream stdout = new BufferedInputStream(p.getInputStream());
109
110 int c = stderr.read();
111 while (c != -1) {
112 buf.write((char)c);
113 c = stderr.read();
114 }
115
116 c = stdout.read();
117 if (c != -1)
118 buf.append("-------------------------------------------");
119
120 while (c != -1) {
121 buf.write((char)c);
122 c = stdout.read();
123 }
124
125 error = buf.toString();
126
127 try
128 {
129 exit_val = p.waitFor();
130 }
131 catch (InterruptedException e)
132 {
133 throw new IOException(e.toString());
134 }
135
136 if (dbg) System.out.println("Exit value: " + exit_val);
137
138 return exit_val == 0;
139 }
140
141 public static void main (String args[]) throws Exception
142 {
143 Args myargs = new Args(args);
144 myargs.setUsage("java " + ClassUtil.getClassName() + " -file path-to-file-to-compile [-classpath <class-path> -encoding encoding]");
145
146 TemplateCompiler pc = new TemplateCompiler(
147 new File(myargs.getRequired("file")),
148 myargs.get("classpath", System.getProperty("java.class.path")));
149
150 if (! pc.compile())
151 System.out.println(pc.getError());
152 }
153 }