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 006package fc.util.pagetemplate; 007 008import java.io.*; 009import java.util.*; 010import fc.util.*; 011 012/** 013Used to compile generated pages by invoking the java compiler. 014*/ 015public class TemplateCompiler 016{ 017private static final boolean dbg = false; 018 019String error; 020File javafile; 021String classpath; 022 023/** 024Creates a new page compiler that will use the default (system) classpath 025as seen by 'javac' when it is invoked from the command line. No 026seperate "encoding" flag will be specified to the javac. 027 028*/ 029public TemplateCompiler(File javafile) 030 { 031 this.javafile = javafile; 032 } 033 034/** 035Creates a new page compiler with the specified classpath. This is useful 036when the classpath must contain some directories within the servlet web 037application, 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*/ 042public TemplateCompiler(File javafile, String classpath) 043 { 044 this.javafile = javafile; 045 this.classpath = classpath; 046 } 047 048public String getError() 049 { 050 return error; 051 } 052 053public 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 141public 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}