Quadcap Embeddable Server

com/quadcap/http/servlets/jsp/JavaCompiler.java

Go to the documentation of this file.
00001 package com.quadcap.http.servlets.jsp; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.ByteArrayOutputStream; 00042 import java.io.File; 00043 import java.io.FileInputStream; 00044 import java.io.FileOutputStream; 00045 import java.io.IOException; 00046 import java.io.InputStream; 00047 import java.io.OutputStream; 00048 00049 import java.util.Properties; 00050 00051 import javax.servlet.ServletContext; 00052 00053 import com.quadcap.http.server22.WebApplication; 00054 00055 import com.quadcap.io.IO; 00056 00057 import com.quadcap.util.Debug; 00058 00059 /** 00060 * Compile java to class files using the configured compiler options. 00061 * 00062 * @author Stan Bailes 00063 */ 00064 public class JavaCompiler { 00065 File root; 00066 String compileCmd; 00067 String contextClassPath = ""; 00068 Properties defaultProps; 00069 00070 public JavaCompiler() {} 00071 00072 public void init(ServletContext context, File root, 00073 String compileCmd, Properties defaultProps) { 00074 this.root = root; 00075 this.compileCmd = compileCmd; 00076 this.defaultProps = defaultProps; 00077 if (context instanceof WebApplication) { 00078 WebApplication app = (WebApplication)context; 00079 contextClassPath = app.getContextClassPath(); 00080 } 00081 } 00082 00083 private Thread copyOutput(final OutputStream os, 00084 final InputStream is) { 00085 return new Thread() { 00086 public void run() { 00087 int c; 00088 try { 00089 IO.copyStream(is, os); 00090 } catch (IOException e) { 00091 } 00092 } 00093 }; 00094 } 00095 00096 String getCompileCommand(Properties props) { 00097 StringBuffer sb = new StringBuffer(); 00098 StringBuffer nb = new StringBuffer(); 00099 int state = 0; 00100 for (int i = 0; i < compileCmd.length(); i++) { 00101 char c = compileCmd.charAt(i); 00102 switch (state) { 00103 case 0: 00104 if (c == '%') { 00105 state = 1; 00106 nb.setLength(0); 00107 } else { 00108 sb.append(c); 00109 } 00110 break; 00111 case 1: 00112 if (c == '%') { 00113 sb.append(c); 00114 state = 0; 00115 } else { 00116 nb.append(c); 00117 state = 2; 00118 } 00119 break; 00120 case 2: 00121 if (c == '%') { 00122 sb.append(props.getProperty(nb.toString())); 00123 state = 0; 00124 } else { 00125 nb.append(c); 00126 } 00127 } 00128 } 00129 return sb.toString(); 00130 } 00131 00132 public boolean doCompile(String cmd, OutputStream out) 00133 throws IOException 00134 { 00135 Process p = Runtime.getRuntime().exec(cmd); 00136 Thread errthread = copyOutput(out, p.getErrorStream()); 00137 Thread outthread = copyOutput(out, p.getInputStream()); 00138 errthread.start(); 00139 outthread.start(); 00140 int res = -1; 00141 try { res = p.waitFor(); } catch (Throwable t) {} 00142 try { errthread.join(); } catch (Throwable t) {} 00143 try { outthread.join(); } catch (Throwable t) {} 00144 return res == 0; 00145 } 00146 00147 public void compile(File javaFile, File classFile) 00148 throws IOException, ClassNotFoundException, JspException 00149 { 00150 Properties cprops = new Properties(defaultProps); 00151 cprops.put("source", javaFile.getPath()); 00152 cprops.put("repository", root.getPath()); 00153 cprops.put("context.classpath", contextClassPath); 00154 String cmd = getCompileCommand(cprops); 00155 if (Trace.level() > 2) { 00156 Debug.println("COMPILE: " + cmd); 00157 } 00158 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 00159 boolean ok = doCompile(cmd, bos); 00160 if (Trace.level() > 3) { 00161 Debug.println("COMPILE OUTPUT: " + bos.toString()); 00162 } 00163 if (!ok) { 00164 throw new JspException("compile failed: " + bos.toString()); 00165 } 00166 if (!classFile.exists()) { 00167 throw new ClassNotFoundException("No class file generated by compile: " + 00168 bos.toString()); 00169 } 00170 } 00171 00172 //#ifdef DEBUG 00173 public static void main(String args[]) { 00174 String cmd = "./jikes -classpath %java.class.path%;%repository%;%java.home%/lib/rt.jar -d %repository% +D +E -nowarn %source%"; 00175 Properties props = System.getProperties(); 00176 try { 00177 JavaCompiler jc = new JavaCompiler(); 00178 jc.init(null, new File("./repository"), cmd, props); 00179 File j = new File("./repository/__jsp/login.java"); 00180 File c = new File("./repository/__jsp/login.class"); 00181 jc.compile(j, c); 00182 } catch (Throwable tt) { 00183 tt.printStackTrace(System.err); 00184 } 00185 } 00186 //#endif 00187 }