1
2
3
4 package net.sf.bddbddb;
5
6 import java.util.Iterator;
7 import java.util.StringTokenizer;
8 import java.io.BufferedWriter;
9 import java.io.File;
10 import java.io.FileWriter;
11 import java.io.FilenameFilter;
12 import java.io.IOException;
13 import java.io.OutputStream;
14 import java.lang.reflect.InvocationTargetException;
15 import java.lang.reflect.Method;
16 import jwutil.io.InputStreamGobbler;
17 import jwutil.io.SystemProperties;
18 import net.sf.javabdd.BDD;
19
20 /***
21 * CodeFragment
22 *
23 * @author jwhaley
24 * @version $Id: CodeFragment.java 605 2005-07-12 01:40:35Z cunkel $
25 */
26 public class CodeFragment {
27
28 static boolean TRACE = false;
29
30 String fragment;
31 Method method;
32
33 /***
34 */
35 public CodeFragment(String string, InferenceRule ir) {
36 this.fragment = string;
37 this.method = genMethod(ir);
38 if (this.method == null) throw new IllegalArgumentException();
39 }
40
41 /***
42 */
43 public CodeFragment(String string, Relation r) {
44 this.fragment = string;
45 this.method = genMethod(r);
46 if (this.method == null) throw new IllegalArgumentException();
47 }
48
49 /***
50 * Find a place for a temp file in classpath.
51 *
52 * @return path in classpath that is writable, or null.
53 */
54 public static File findWritablePath() {
55
56 String cp = SystemProperties.getProperty("java.class.path");
57 StringTokenizer st = new StringTokenizer(cp, SystemProperties.getProperty("path.separator"));
58 while (st.hasMoreTokens()) {
59 String p = st.nextToken();
60 File f = new File(p);
61 if (!f.isDirectory()) continue;
62 if (!f.canWrite()) continue;
63 if (TRACE) System.out.println("Path for code fragment: "+f);
64 return f;
65 }
66 return null;
67 }
68
69 /***
70 * Search for javac executable.
71 *
72 * @return path to javac executable, or null
73 */
74 static String searchForJavac(String path, String[] dirs) {
75 String sep = SystemProperties.getProperty("file.separator");
76 for (int i = 0; i < dirs.length; ++i) {
77 File f2 = new File(path+sep+dirs[i]+sep+"bin"+sep+"javac");
78 if (f2.exists()) return f2.getAbsolutePath();
79 f2 = new File(path+sep+dirs[i]+sep+"bin"+sep+"javac.exe");
80 if (f2.exists()) return f2.getAbsolutePath();
81 }
82 return null;
83 }
84
85 /***
86 * Try to find where javac executable is installed.
87 *
88 * @return path to javac, or null.
89 */
90 public static String findJavac() {
91
92 try {
93 Process p = Runtime.getRuntime().exec("javac");
94 new InputStreamGobbler(p.getInputStream(), (OutputStream)null).start();
95 new InputStreamGobbler(p.getErrorStream(), (OutputStream)null).start();
96 int c = p.waitFor();
97 return "javac";
98 } catch (IOException e) {
99 } catch (InterruptedException e) {
100 }
101 try {
102 Process p = Runtime.getRuntime().exec("jikes");
103 new InputStreamGobbler(p.getInputStream(), (OutputStream)null).start();
104 new InputStreamGobbler(p.getErrorStream(), (OutputStream)null).start();
105 int c = p.waitFor();
106 return "jikes";
107 } catch (IOException e) {
108 } catch (InterruptedException e) {
109 }
110
111
112 String path = SystemProperties.getProperty("java.home");
113 String sep = SystemProperties.getProperty("file.separator");
114 FilenameFilter filter = new FilenameFilter() {
115 public boolean accept(File dir, String name) {
116 if (name.startsWith("jdk")) return true;
117 if (name.startsWith("j2sdk")) return true;
118 return false;
119 }
120 };
121
122 File f = new File(path+sep+"..");
123 String[] s = f.list(filter);
124 String s2 = searchForJavac(path+sep+"..", s);
125 if (s2 != null) return s2;
126
127
128 f = new File(sep);
129 s = f.list(filter);
130 s2 = searchForJavac(sep, s);
131 if (s2 != null) return s2;
132
133
134 f = new File("/usr/java/bin/javac");
135 if (f.exists()) return f.getAbsolutePath();
136 f = new File("/usr/java");
137 s = f.list(filter);
138 if (s != null) s2 = searchForJavac("/usr/java", s);
139 if (s2 != null) return s2;
140
141
142 return null;
143 }
144
145 Method genMethod(Object o) {
146 File path = findWritablePath();
147 if (path == null) {
148 System.err.println("Cannot find writable directory in class path, skipping code fragment generation.");
149 return null;
150 }
151 String javacName = findJavac();
152 if (javacName == null) {
153 System.err.println("Cannot find java compiler, skipping code fragment generation.");
154 return null;
155 }
156 if (TRACE) System.out.println("Using Java compiler "+javacName);
157
158 String className;
159 try {
160
161 File temp = File.createTempFile("frag", ".java", path);
162
163
164 temp.deleteOnExit();
165
166
167 className = temp.getName();
168 className = className.substring(0, className.length()-5);
169 if (TRACE) System.out.println("Writing temporary file for code fragment to: "+temp);
170
171
172 BufferedWriter out = new BufferedWriter(new FileWriter(temp));
173 out.write("import net.sf.bddbddb.*;\nimport net.sf.javabdd.*;\n");
174 out.write("import net.sf.bddbddb.dataflow.*;\nimport net.sf.bddbddb.ir.*;\nimport net.sf.bddbddb.order.*;\n\n");
175 out.write("public class ");
176 out.write(className);
177 out.write(" {\n public static void go(");
178 if (o instanceof BDDInferenceRule) {
179 BDDInferenceRule ir = (BDDInferenceRule) o;
180 out.write("BDDInferenceRule rule, BDD val) throws Exception {\n");
181 out.write(" java.util.List subgoals = rule.getSubgoals();\n");
182 int k = 0;
183 for (Iterator i = ir.top.iterator(); i.hasNext(); ) {
184 RuleTerm rt = (RuleTerm) i.next();
185 out.write(" RuleTerm subgoal"+k+" = (RuleTerm) subgoals.get("+k+");\n");
186 out.write(" Relation "+rt.relation.name+" = subgoal"+k+".getRelation();\n");
187 ++k;
188 }
189 out.write(" RuleTerm head = rule.getHead();\n");
190 out.write(" Relation "+ir.bottom.relation.name+" = head.getRelation();\n");
191 } else {
192 BDDRelation r = (BDDRelation) o;
193 out.write("BDDRelation "+r.name+", BDD val) throws Exception {\n");
194 }
195 out.write(fragment);
196 out.write("\n }\n}\n");
197 out.close();
198
199 String cp = SystemProperties.getProperty("java.class.path");
200 Process javac = Runtime.getRuntime().exec(
201 new String[] { javacName, "-source", "1.3", "-target", "1.3",
202 "-classpath", cp, className+".java" }, null, path);
203 new InputStreamGobbler(javac.getInputStream(), System.out).start();
204 new InputStreamGobbler(javac.getErrorStream(), System.err).start();
205 javac.waitFor();
206 int rc = javac.exitValue();
207 if (rc != 0) {
208 System.err.println("Error occurred while compiling code fragment: "+rc);
209 return null;
210 }
211 File classFile = new File(path, className+".class");
212 classFile.deleteOnExit();
213
214 Class c = Class.forName(className);
215 try {
216 Class type = (o instanceof BDDInferenceRule) ? BDDInferenceRule.class : BDDRelation.class;
217 Method method = c.getDeclaredMethod("go", new Class[] { type, BDD.class });
218 return method;
219 } catch (SecurityException e) {
220 System.err.println("Security exception occurred while accessing method for code fragment.");
221 } catch (NoSuchMethodException e) {
222 System.err.println("Cannot find method for code fragment.");
223 }
224 } catch (IOException e) {
225 System.err.println("Error occurred while writing class file for code fragment: "+e);
226 } catch (InterruptedException e) {
227 System.err.println("Error: compilation of code fragment was interrupted.");
228 } catch (ClassNotFoundException e) {
229 System.err.println("Error: cannot find compiled code fragment.");
230 }
231 return null;
232 }
233
234 /***
235 * @param rule
236 * @param oldValue
237 */
238 public void invoke(InferenceRule rule, BDD oldValue) {
239 if (method == null) return;
240 try {
241 method.invoke(null, new Object[] { rule, oldValue });
242 } catch (IllegalArgumentException e) {
243
244 e.printStackTrace();
245 } catch (IllegalAccessException e) {
246
247 e.printStackTrace();
248 } catch (InvocationTargetException e) {
249
250 if (e.getCause() instanceof RuntimeException) {
251 throw (RuntimeException) e.getCause();
252 }
253 e.printStackTrace();
254 }
255 }
256
257 /***
258 * @param r
259 * @param oldValue
260 */
261 public void invoke(Relation r, BDD oldValue) {
262 if (method == null) return;
263 try {
264 method.invoke(null, new Object[] { r, oldValue });
265 } catch (IllegalArgumentException e) {
266
267 e.printStackTrace();
268 } catch (IllegalAccessException e) {
269
270 e.printStackTrace();
271 } catch (InvocationTargetException e) {
272
273 if (e.getCause() instanceof RuntimeException) {
274 throw (RuntimeException) e.getCause();
275 }
276 e.printStackTrace();
277 }
278 }
279 }