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