Timtower

Compiler

Aug 18th, 2014
579
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.28 KB | None | 0 0
  1. package nl.timdebrouwer.dynamiccompileandload;
  2.  
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.net.URI;
  6. import java.util.Arrays;
  7. import java.util.logging.Logger;
  8.  
  9. import javax.tools.Diagnostic;
  10. import javax.tools.DiagnosticCollector;
  11. import javax.tools.JavaCompiler;
  12. import javax.tools.JavaCompiler.CompilationTask;
  13. import javax.tools.JavaFileObject;
  14. import javax.tools.SimpleJavaFileObject;
  15. import javax.tools.StandardJavaFileManager;
  16. import javax.tools.ToolProvider;
  17.  
  18. /**
  19. * A test class to test dynamic compilation API.
  20. *
  21. */
  22. public class Compiler {
  23. final Logger logger = Logger.getLogger(Compiler.class.getName()) ;
  24.  
  25. /**Java source code to be compiled dynamically*/
  26. /*static String sourceCode = "package com.accordess.ca;" +
  27. "class DynamicCompilationHelloWorld{" +
  28. "public static void main (String args[]){" +
  29. "System.out.println (\"Hello, dynamic compilation world!\");" +
  30. "}" +
  31. "}" */
  32.  
  33. /**
  34. * Does the required object initialization and compilation.
  35. */
  36. public static void doCompilation (SimpleJavaFileObject fileObject){
  37. /*Creating dynamic java source code file object*/
  38. //SimpleJavaFileObject fileObject = new DynamicJavaSourceCodeObject ("com.accordess.ca.DynamicCompilationHelloWorld", sourceCode) ;
  39. JavaFileObject javaFileObjects[] = new JavaFileObject[]{fileObject} ;
  40.  
  41. /*Instantiating the java compiler*/
  42. JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  43. if(compiler==null){
  44. System.out.println("Compiler is dood");
  45. return;
  46. }
  47. /**
  48. * Retrieving the standard file manager from compiler object, which is used to provide
  49. * basic building block for customizing how a compiler reads and writes to files.
  50. *
  51. * The same file manager can be reopened for another compiler task.
  52. * Thus we reduce the overhead of scanning through file system and jar files each time
  53. */
  54. StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null);
  55.  
  56. /* Prepare a list of compilation units (java source code file objects) to input to compilation task*/
  57. Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(javaFileObjects);
  58.  
  59. /*Prepare any compilation options to be used during compilation*/
  60. //In this example, we are asking the compiler to place the output files under bin folder.
  61. //String[] compileOptions = new String[]{"-d", "bin"} ;
  62. String[] compileOptions = new String[]{"-d", "compiled"} ;
  63. File folder = new File(compileOptions[1]);
  64. if(!folder.exists()){
  65. try{
  66. folder.mkdirs();
  67. }catch(Exception e){
  68.  
  69. }
  70. }
  71. Iterable<String> compilationOptionss = Arrays.asList(compileOptions);
  72.  
  73. /*Create a diagnostic controller, which holds the compilation problems*/
  74. DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
  75.  
  76. /*Create a compilation task from compiler by passing in the required input objects prepared above*/
  77. CompilationTask compilerTask = compiler.getTask(null, stdFileManager, diagnostics, compilationOptionss, null, compilationUnits) ;
  78.  
  79. //Perform the compilation by calling the call method on compilerTask object.
  80. boolean status = compilerTask.call();
  81.  
  82. if (!status){//If compilation error occurs
  83. /*Iterate through each compilation problem and print it*/
  84. for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()){
  85. System.out.format("Error on line %d in %s", diagnostic.getLineNumber(), diagnostic);
  86. }
  87. }
  88. try {
  89. stdFileManager.close() ;//Close the file manager
  90. } catch (IOException e) {
  91. e.printStackTrace();
  92. }
  93. }
  94.  
  95. public static void main(String args[]){
  96. //new Compiler ().doCompilation() ;
  97. }
  98.  
  99. }
  100.  
  101. /**
  102. * Creates a dynamic source code file object
  103. *
  104. * This is an example of how we can prepare a dynamic java source code for compilation.
  105. * This class reads the java code from a string and prepares a JavaFileObject
  106. *
  107. */
  108. class DynamicJavaSourceCodeObject extends SimpleJavaFileObject{
  109. private String qualifiedName ;
  110. private String sourceCode ;
  111.  
  112. /**
  113. * Converts the name to an URI, as that is the format expected by JavaFileObject
  114. *
  115. *
  116. * @param fully qualified name given to the class file
  117. * @param code the source code string
  118. */
  119. protected DynamicJavaSourceCodeObject(String name, String code) {
  120. super(URI.create("string:///" +name.replaceAll("\\.", "/") + Kind.SOURCE.extension), Kind.SOURCE);
  121. this.qualifiedName = name ;
  122. this.sourceCode = code ;
  123. }
  124.  
  125. @Override
  126. public CharSequence getCharContent(boolean ignoreEncodingErrors)
  127. throws IOException {
  128. return sourceCode ;
  129. }
  130.  
  131. public String getQualifiedName() {
  132. return qualifiedName;
  133. }
  134.  
  135. public void setQualifiedName(String qualifiedName) {
  136. this.qualifiedName = qualifiedName;
  137. }
  138.  
  139. public String getSourceCode() {
  140. return sourceCode;
  141. }
  142.  
  143. public void setSourceCode(String sourceCode) {
  144. this.sourceCode = sourceCode;
  145. }
  146. }
  147.  
  148.  
  149.  
  150. ===== END CLASS COMPILER =====
  151.  
  152. package nl.timdebrouwer.dynamiccompileandload;
  153.  
  154. import java.io.File;
  155. import java.lang.reflect.Field;
  156. import java.lang.reflect.Method;
  157. import java.net.URI;
  158. import java.net.URL;
  159. import java.net.URLClassLoader;
  160. import java.util.ArrayList;
  161. import java.util.List;
  162. import java.util.Scanner;
  163. import java.util.regex.Matcher;
  164. import java.util.regex.Pattern;
  165.  
  166. import javax.tools.SimpleJavaFileObject;
  167.  
  168. @SuppressWarnings("unused")
  169. public class DynamicCompileAndLoad{
  170. private File classFolder;
  171. private List<ClassFile> classFiles;
  172. public URLClassLoader loader;
  173.  
  174. public static void main(String args[]){
  175. DynamicCompileAndLoad loader = new DynamicCompileAndLoad();
  176. }
  177.  
  178. public DynamicCompileAndLoad(){
  179. File inputFolder = new File("scripts");
  180. List<File> javaFiles = getFiles(inputFolder);
  181. classFiles = new ArrayList<ClassFile>();
  182.  
  183. classFolder = new File("compiled");
  184. if(!inputFolder.exists()){
  185. inputFolder.mkdir();
  186. }
  187. if(!classFolder.exists()){
  188. classFolder.mkdir();
  189. }
  190. try{
  191. loader = new URLClassLoader(new URL[]{classFolder.toURI().toURL()},DynamicCompileAndLoad.class.getClassLoader());
  192. deleteFiles(classFolder);
  193. }catch(Exception e){
  194. e.printStackTrace();
  195. }
  196. if(!classFolder.exists()){
  197. classFolder.mkdir();
  198. }
  199. for(File file:javaFiles){
  200. try{
  201. Scanner scanner = new Scanner(file);
  202. String code = "";
  203. String pack = null;
  204. String name = stripName(file.getAbsolutePath());
  205. while(scanner.hasNext()){
  206. String line = scanner.nextLine();
  207. code = code+"\n"+line;
  208. if(line.startsWith("package")){
  209. pack = line.split(" ")[1];
  210. pack = pack.substring(0, pack.length()-1);
  211. //System.out.println("Package: " + pack);
  212. }
  213. }
  214. scanner.close();
  215. List<String> methods = getMethods(code);
  216. List<String> imports = getImports(code);
  217. ClassFile f = new ClassFile();
  218. f.source = code;
  219. //System.out.println(pack + " "+name);
  220. f.name = name;
  221. f.pack = pack;
  222. f.imports = imports;
  223. f.methods = methods;
  224. classFiles.add(f);
  225. }catch(Exception e){
  226. e.printStackTrace();
  227. }
  228. }
  229. System.out.println("First compilation");
  230. for(ClassFile file:classFiles){
  231. compileFirst(file);
  232. }
  233. System.out.println("");
  234. System.out.println("");
  235. System.out.println("Second compilation");
  236. for(ClassFile file:classFiles){
  237. compileSecond(file);
  238. }
  239. System.out.println("");
  240. System.out.println("");
  241. System.out.println("Last compilation");
  242. for(ClassFile file:classFiles){
  243. compileThird(file);
  244. }
  245. System.out.println("");
  246. System.out.println("");
  247. System.out.println("");
  248. System.out.println("Done compiling");
  249. System.out.println("");
  250. System.out.println("");
  251. try{
  252. Class<?> clazz = Class.forName("nl.timdebrouwer.helloworld.EmptyClass");
  253. }catch(Exception e){
  254. e.printStackTrace();
  255. }
  256. for(ClassFile file:classFiles){
  257. System.out.println(file.clazz.getName());
  258. }
  259. }
  260.  
  261. private void compileThird(ClassFile file) {
  262. try{
  263. Field uriField;
  264. Class<?> c;
  265. c = SimpleJavaFileObject.class;
  266. uriField = c.getDeclaredField("uri");
  267. uriField.setAccessible(true);
  268. String pack = file.pack;
  269. String name = file.name;
  270. String code = file.source;
  271. DynamicJavaSourceCodeObject ob = new DynamicJavaSourceCodeObject(pack,code);
  272. URI oldURI = ob.toUri();
  273. //System.out.println(oldURI.toString());
  274. //URI newURI = new URI(oldURI.toString().replaceAll(name.toLowerCase(), name));
  275. String first = oldURI.toString().split(name.toLowerCase())[0].replaceAll(".java", "") + "/" + name+".java";
  276. //System.out.println("First: "+first);
  277. //URI newURI = new URI(oldURI.toString());
  278. URI newURI = new URI(first);
  279. //System.out.println(newURI.toString());
  280. uriField.set(ob, newURI);
  281. Compiler.doCompilation(ob);
  282. //System.out.println(pack+"."+name);
  283. Class<?> clazz = loader.loadClass(pack+"."+name);
  284. Object instance = clazz.newInstance();
  285. file.clazz = clazz;
  286. //loader.close();
  287. }catch(Exception e){
  288. e.printStackTrace();
  289. }
  290. }
  291.  
  292. private void compileSecond(ClassFile file) {
  293. try{
  294. Field uriField;
  295. Class<?> c;
  296. c = SimpleJavaFileObject.class;
  297. uriField = c.getDeclaredField("uri");
  298. uriField.setAccessible(true);
  299. String pack = file.pack;
  300. String name = file.name;
  301. String code = "package "+pack+";\n";
  302. for(String impor:file.imports){
  303. code = code + impor+"\n";
  304. }
  305. code = code+"public class "+name+"{";
  306. for(String method:file.methods){
  307. code = code + method+"\n";
  308. }
  309. code = code + "}";
  310. DynamicJavaSourceCodeObject ob = new DynamicJavaSourceCodeObject(pack,code);
  311. URI oldURI = ob.toUri();
  312. //System.out.println(oldURI.toString());
  313. //URI newURI = new URI(oldURI.toString().replaceAll(name.toLowerCase(), name));
  314. String first = oldURI.toString().split(name.toLowerCase())[0].replaceAll(".java", "") + "/" + name+".java";
  315. //System.out.println("First: "+first);
  316. //URI newURI = new URI(oldURI.toString());
  317. URI newURI = new URI(first);
  318. //System.out.println(newURI.toString());
  319. uriField.set(ob, newURI);
  320. Compiler.doCompilation(ob);
  321. //System.out.println(pack+"."+name);
  322. //URLClassLoader loader = new URLClassLoader(new URL[]{classFolder.toURI().toURL()},DynamicCompileAndLoad.class.getClassLoader());
  323. Class<?> clazz = loader.loadClass(pack+"."+name);
  324. file.clazz = clazz;
  325. //loader.close();
  326. }catch(Exception e){
  327. e.printStackTrace();
  328. }
  329. }
  330.  
  331. private void compileFirst(ClassFile file) {
  332. try{
  333. Field uriField;
  334. Class<?> c;
  335. c = SimpleJavaFileObject.class;
  336. uriField = c.getDeclaredField("uri");
  337. uriField.setAccessible(true);
  338. String pack = file.pack;
  339. String name = file.name;
  340. String code = "package "+pack+"; public class "+name+"{}";
  341. //System.out.println(pack);
  342. DynamicJavaSourceCodeObject ob = new DynamicJavaSourceCodeObject(pack,code);
  343. URI oldURI = ob.toUri();
  344. //System.out.println(oldURI.toString());
  345. //URI newURI = new URI(oldURI.toString().replaceAll(name.toLowerCase(), name));
  346. String first = oldURI.toString().split(name.toLowerCase())[0].replaceAll(".java", "") + "/" + name+".java";
  347. //System.out.println("First: "+first);
  348. //URI newURI = new URI(oldURI.toString());
  349. URI newURI = new URI(first);
  350. //System.out.println(newURI.toString());
  351. uriField.set(ob, newURI);
  352. Compiler.doCompilation(ob);
  353. //System.out.println(pack+"."+name);
  354. //URLClassLoader loader = new URLClassLoader(new URL[]{classFolder.toURI().toURL()},DynamicCompileAndLoad.class.getClassLoader());
  355. Class<?> clazz = loader.loadClass(pack+"."+name);
  356. file.clazz = clazz;
  357. //loader.close();
  358. }catch(Exception e){
  359. e.printStackTrace();
  360. }
  361. }
  362.  
  363. private String stripName(String input) {
  364. String[] parts = input.split(Pattern.quote(File.separator));
  365. String name = parts[parts.length-1].split(Pattern.quote("."))[0];
  366. return name;
  367. }
  368.  
  369. private List<File> getFiles(File inputFolder) {
  370. List<File> fileList = new ArrayList<File>();
  371. for(File file:inputFolder.listFiles()){
  372. if(file.isDirectory()){
  373. fileList.addAll(getFiles(file));
  374. continue;
  375. }
  376. if(file.getAbsolutePath().toLowerCase().endsWith(".java")){
  377. fileList.add(file.getAbsoluteFile());
  378. }
  379. }
  380. return fileList;
  381. }
  382.  
  383. private void deleteFiles(File inputFolder) {
  384. for(File file:inputFolder.listFiles()){
  385. if(file.isDirectory()){
  386. deleteFiles(file);
  387. }else{
  388. file.delete();
  389. }
  390. }
  391. }
  392.  
  393. private static List<String> getMethods(String source){
  394. List<String> functions = new ArrayList<String>();
  395. //Pattern pattern = Pattern.compile("^\\s*(public|private|protected|static|abstract)*");
  396. Pattern pattern = Pattern.compile("((public|private|protected|static|abstract)\\s)+(\\S+\\s*){2}[(](\\S+\\s\\S+)*[)]");
  397. Matcher match = pattern.matcher(source);
  398. while(match.find()){
  399. String reg = match.group();
  400. if(!reg.isEmpty()){
  401. //System.out.println("Method found: '"+reg+"'");
  402. String returns = "void";
  403. Pattern returnPattern = Pattern.compile("((public|private|protected|static|abstract)\\s)+(\\S+\\s*){1}");
  404. Matcher returnMatch = returnPattern.matcher(reg);
  405. returnMatch.find();
  406. returns = returnMatch.group();
  407. returnPattern = Pattern.compile("((public|private|protected|static|abstract)\\s)+");
  408. returnMatch = returnPattern.matcher(returns);
  409. returnMatch.find();
  410. String returnsStrip = returnMatch.group();
  411. returns = returns.split(returnsStrip)[1];
  412. //System.out.println("Returns "+returns);
  413. if(returns.equalsIgnoreCase("void ")){
  414. //System.out.println("Something returns void");
  415. functions.add(reg+"{}");
  416. continue;
  417. }
  418. if(returns.equalsIgnoreCase("boolean ")){
  419. //System.out.println("Something returns boolean");
  420. functions.add(reg+"{return false;}");
  421. continue;
  422. }
  423. if(returns.equalsIgnoreCase("int ") || returns.equalsIgnoreCase("double ") || returns.equalsIgnoreCase("float ")){
  424. //System.out.println("Something returns void");
  425. functions.add(reg+"{return 0;}");
  426. continue;
  427. }
  428. functions.add(reg+"{return null;}");
  429. continue;
  430. }
  431. }
  432. return functions;
  433. }
  434.  
  435. private static List<String> getImports(String source){
  436. List<String> functions = new ArrayList<String>();
  437. //Pattern pattern = Pattern.compile("^\\s*(public|private|protected|static|abstract)*");
  438. Pattern pattern = Pattern.compile("(import\\s){1}(\\S)+;");
  439. Matcher match = pattern.matcher(source);
  440. while(match.find()){
  441. String reg = match.group();
  442. if(!reg.isEmpty()){
  443. reg = reg.split(" ")[1];
  444. //System.out.println("Import found: '"+reg+"'");
  445. functions.add("import "+reg);
  446. }
  447. }
  448. return functions;
  449. }
  450.  
  451. private static Field getField(Class<?> clazz, String fieldName)throws NoSuchFieldException {
  452. try {
  453. Field f = clazz.getDeclaredField(fieldName);
  454. //System.out.println(clazz.getName());
  455. return f;
  456. } catch (NoSuchFieldException e) {
  457. Class<?> superClass = clazz.getSuperclass();
  458. if (superClass == null) {
  459. throw e;
  460. } else {
  461. return getField(superClass, fieldName);
  462. }
  463. }
  464. }
  465. }
  466.  
  467. ===== END MAIN CLASS =====
  468.  
  469.  
  470. package nl.timdebrouwer.dynamiccompileandload;
  471.  
  472. import java.net.URI;
  473. import java.util.List;
  474.  
  475. public class ClassFile {
  476. public String name;
  477. public URI path;
  478. public String pack;
  479. public String source;
  480. public List<String> imports;
  481. public List<String> methods;
  482. public Class<?> clazz;
  483. }
  484.  
  485.  
  486. ===== END STORAGE CLASS
Advertisement
Add Comment
Please, Sign In to add comment