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.web.page; 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 PageCompiler 016 { 017 private static final boolean dbg = false; 018 019 String error; 020 File javafile; 021 String classpath; 022 String encoding; 023 024 /** 025 Creates a new page compiler that will use the default (system) classpath 026 as seen by 'javac' when it is invoked from the command line. No 027 seperate "encoding" flag will be specified to the javac. 028 029 */ 030 public PageCompiler(File javafile) 031 { 032 this.javafile = javafile; 033 } 034 035 /** 036 Creates a new page compiler with the specified classpath. This is useful 037 when the classpath must contain some directories within the servlet web 038 application, 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 */ 047 public PageCompiler(File javafile, String classpath, String encoding) 048 { 049 this.javafile = javafile; 050 this.classpath = classpath; 051 this.encoding = encoding; 052 } 053 054 public String getError() 055 { 056 return error; 057 } 058 059 public 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 149 public 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 }