1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package org.openrdf.elmo.codegen;
30
31 import java.io.BufferedReader;
32 import java.io.File;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.InputStreamReader;
36 import java.io.OutputStream;
37 import java.lang.reflect.InvocationTargetException;
38 import java.lang.reflect.Method;
39 import java.net.URL;
40 import java.net.URLClassLoader;
41 import java.util.ArrayList;
42 import java.util.List;
43
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public class JavaCompiler {
48
49 final Logger logger = LoggerFactory.getLogger(JavaCompiler.class);
50
51 private String version = "5";
52
53 public String getVersion() {
54 return version;
55 }
56
57 public void setVersion(String version) {
58 this.version = version;
59 }
60
61 public void compile(File dir, List<String> content, URLClassLoader cl) throws Exception {
62 List<File> classpath = new ArrayList<File>();
63 for (URL jar : cl.getURLs()) {
64 classpath.add(new File(jar.getPath()));
65 }
66 String classPath = System.getProperty("java.class.path");
67 for (String path : classPath.split(File.pathSeparator)) {
68 classpath.add(new File(path));
69 }
70 List<File> source = new ArrayList<File>();
71 for (String name : content) {
72 String filename = name.replace('.', File.separatorChar);
73 source.add(new File(dir, filename + ".java"));
74 }
75 if (javac(buildJavacArgs(source, classpath)) != 0)
76 throw new AssertionError("Could not compile");
77 }
78
79 private int javac(String[] args) throws Exception {
80 try {
81 return javaCompilerTool(args);
82 } catch (Exception e) {
83 }
84 try {
85 return javaSunTools(args);
86 } catch (Exception e) {
87 }
88 return javacCommand(args);
89 }
90
91
92
93
94 private int javaCompilerTool(String[] args) throws Exception {
95 Class<?> provider = Class.forName("javax.tools.ToolProvider");
96 Method getJavaCompiler = provider.getMethod("getSystemJavaCompiler");
97 Class<?> tool = Class.forName("javax.tools.Tool");
98 Method run = tool.getMethod("run", InputStream.class,
99 OutputStream.class, OutputStream.class, args.getClass());
100 Object compiler = getJavaCompiler.invoke(null);
101 logger.debug("invoke javax.tools.JavaCompiler#run");
102 try {
103 Object[] param = new Object[] { null, null, null, args };
104 Object result = run.invoke(compiler, param);
105 return ((Number) result).intValue();
106 } catch (InvocationTargetException e) {
107 if (e.getCause() instanceof Exception)
108 throw (Exception) e.getCause();
109 throw e;
110 }
111 }
112
113
114
115
116 private int javaSunTools(String[] args) throws Exception {
117 Class<?> sun = Class.forName("com.sun.tools.javac.Main");
118 Method method = sun.getMethod("compile", args.getClass());
119 logger.debug("invoke com.sun.tools.javac.Main#compile");
120 try {
121 Object result = method.invoke(null, new Object[] { args });
122 return ((Number) result).intValue();
123 } catch (InvocationTargetException e) {
124 if (e.getCause() instanceof Exception)
125 throw (Exception) e.getCause();
126 throw e;
127 }
128 }
129
130
131
132
133 private int javacCommand(String[] args) throws Exception {
134 return exec(findJavac(), args);
135 }
136
137 private String findJavac() {
138 String javac = findJavac(System.getProperty("jdk.home"));
139 if (javac == null)
140 javac = findJavac(System.getProperty("java.home"));
141 if (javac == null)
142 javac = findJavac(System.getenv("JAVA_HOME"));
143 if (javac == null) {
144 String systemPath = System.getenv("PATH");
145 for (String path : systemPath.split(File.pathSeparator)) {
146 File file = new File(path, "javac");
147 if (file.exists())
148 return file.getPath();
149 }
150 }
151 if (javac == null)
152 throw new AssertionError("No compiler found");
153 return javac;
154 }
155
156 private String findJavac(String home) {
157 if (home == null)
158 return null;
159 File javac = new File(new File(home, "bin"), "javac");
160 if (javac.exists())
161 return javac.getPath();
162 javac = new File(new File(home, "bin"), "javac.exe");
163 if (javac.exists())
164 return javac.getPath();
165 File parent = new File(home).getParentFile();
166 javac = new File(new File(parent, "bin"), "javac");
167 if (javac.exists())
168 return javac.getPath();
169 javac = new File(new File(parent, "bin"), "javac.exe");
170 if (javac.exists())
171 return javac.getPath();
172 return null;
173 }
174
175 private int exec(String cmd, String[] args) throws IOException,
176 InterruptedException {
177 logger.debug("exec {}", cmd);
178 String[] cmdArray = new String[1 + args.length];
179 cmdArray[0] = cmd;
180 System.arraycopy(args, 0, cmdArray, 1, args.length);
181 final Process exec = Runtime.getRuntime().exec(cmdArray);
182 Thread gobbler = new Thread() {
183 @Override
184 public void run() {
185 try {
186 InputStream in = exec.getInputStream();
187 InputStreamReader isr = new InputStreamReader(in);
188 BufferedReader br = new BufferedReader(isr);
189 String line = null;
190 while ((line = br.readLine()) != null)
191 System.out.println(line);
192 } catch (IOException ioe) {
193 logger.error(ioe.getMessage(), ioe);
194 }
195 }
196 };
197 gobbler.start();
198 InputStream stderr = exec.getErrorStream();
199 InputStreamReader isr = new InputStreamReader(stderr);
200 BufferedReader br = new BufferedReader(isr);
201 String line = null;
202 while ((line = br.readLine()) != null)
203 System.err.println(line);
204 return exec.waitFor();
205 }
206
207 private String[] buildJavacArgs(List<File> sources, List<File> classpath) {
208 String[] args = new String[6 + sources.size()];
209 args[0] = "-source";
210 args[1] = version;
211 args[2] = "-target";
212 args[3] = version;
213 args[4] = "-classpath";
214 StringBuilder sb = new StringBuilder();
215 for (File jar : classpath) {
216 sb.append(jar.getAbsolutePath());
217 sb.append(File.pathSeparatorChar);
218 }
219 args[5] = sb.toString();
220 for (int i = 0, n = sources.size(); i < n; i++) {
221 args[6 + i] = sources.get(i).getAbsolutePath();
222 }
223 return args;
224 }
225 }