/** * Given class of the interface for a fluid engine, build a concrete instance of that interface * that calls back into a Basic Engine for all methods in the interface. */ private static BasicEngine buildCallbackEngine(String engineInterface, Class cEngine) { // build up list of callbacks for <engineInterface> StringBuffer decls = new StringBuffer(); Method[] engineMethods = cEngine.getMethods(); for (int i = 0; i < engineMethods.length; i++) { Method meth = engineMethods[i]; // skip methods that aren't declared in the interface if (meth.getDeclaringClass() != cEngine) { continue; } decls.append( " public " + Utils.asTypeDecl(meth.getReturnType()) + " " + meth.getName() + "("); Class[] params = meth.getParameterTypes(); for (int j = 0; j < params.length; j++) { decls.append(Utils.asTypeDecl(params[j]) + " p" + j); if (j != params.length - 1) { decls.append(", "); } } decls.append(") {\n"); decls.append( " return (" + Utils.asTypeDecl(meth.getReturnType()) + ")super.callNative(\"" + meth.getName() + "\", new Object[] {"); for (int j = 0; j < params.length; j++) { decls.append("p" + j); if (j != params.length - 1) { decls.append(", "); } } decls.append("} );\n"); decls.append(" }\n\n"); } // write template file String engineName = "BasicEngine_" + engineInterface; String fileName = engineName + ".java"; try { String contents = Utils.readFile("lava/engine/basic/BasicEngineTemplate.java").toString(); // remove package name contents = Utils.replaceAll(contents, "package lava.engine.basic;", ""); // for class decl contents = Utils.replaceAll( contents, "extends BasicEngine", "extends BasicEngine implements " + engineInterface); // for constructor contents = Utils.replaceAll(contents, "BasicEngineTemplate", engineName); // for methods contents = Utils.replaceAll(contents, "// INSERT METHODS HERE", decls.toString()); Utils.writeFile(fileName, contents); } catch (IOException e) { e.printStackTrace(); System.exit(1); } // compile the file try { Process jProcess = Runtime.getRuntime().exec("jikes " + fileName, null, null); jProcess.waitFor(); } catch (Exception e) { System.err.println("Error compiling auto-generated file " + fileName); e.printStackTrace(); System.exit(1); } // instantiate the class BasicEngine result = null; try { result = (BasicEngine) Class.forName(engineName).newInstance(); // cleanup the files we made new File(engineName + ".java").delete(); new File(engineName + ".class").delete(); } catch (Exception e) { e.printStackTrace(); System.exit(1); } return result; }