JavaCompiler refactored to compile completely in memory. development
authorJan Vrany <jan.vrany@fit.cvut.cz>
Wed, 02 Jan 2013 18:48:11 +0100
branchdevelopment
changeset 1921 a395d5c696b9
parent 1920 45e53b66fe41
child 1922 7fa6a6a8f1d8
JavaCompiler refactored to compile completely in memory. Now JavaCompiler compiles all classes in memory, without saving files to the filesystem. This is achieved by supplying special JavaFileObjects.
JavaClassRegistry.st
JavaInitializedResource.st
examples/java/src/stx/libjava/examples/JavacExample.java
examples/java/src/stx/libjava/examples/JavacExample2.java
experiments/JavaCompiler.st
experiments/JavaCompilerTests.st
experiments/java/src/stx/libjava/benchmarks/B1.java
experiments/java/src/stx/libjava/tools/compiler/JavaClassFile.java
experiments/java/src/stx/libjava/tools/compiler/JavaClassFileManager.java
experiments/java/src/stx/libjava/tools/compiler/JavaCompilerAdapter.java
experiments/java/src/stx/libjava/tools/compiler/JavaSourceFile.java
tools/java/src/stx/libjava/tools/SyntaxHighlighter.java
tools/java/src/stx/libjava/tools/tests/SyntaxHighlighterTests.java
--- a/JavaClassRegistry.st	Wed Jan 02 16:10:35 2013 +0100
+++ b/JavaClassRegistry.st	Wed Jan 02 18:48:11 2013 +0100
@@ -394,6 +394,12 @@
     "Created: / 04-04-2012 / 10:01:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
+registerClasses: classes
+    classes do:[:cls|self registerClass: cls].
+
+    "Created: / 02-01-2013 / 17:01:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 unregisterClass: oldClass
     | classes |
 
@@ -447,6 +453,12 @@
     loaders removeKey: aJavaClassLoader ifAbsent: nil.
 
     "Created: / 16-12-2012 / 16:39:45 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+!
+
+unregisterClasses: classes
+    classes do:[:cls|self unregisterClass: cls].
+
+    "Created: / 02-01-2013 / 17:01:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !JavaClassRegistry class methodsFor:'documentation'!
--- a/JavaInitializedResource.st	Wed Jan 02 16:10:35 2013 +0100
+++ b/JavaInitializedResource.st	Wed Jan 02 18:48:11 2013 +0100
@@ -68,7 +68,7 @@
 
     | java_lang_System |
 
-        (java_lang_System := Java at: 'java.lang.System') ifNil:[
+    (java_lang_System := Java at: 'java.lang.System') ifNil:[
         Java initialize.
         JavaVM initializeVM.
     ] ifNotNil:[
@@ -77,6 +77,7 @@
     super setUp.
 
     "Created: / 16-03-2011 / 14:42:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (format): / 02-01-2013 / 15:16:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !JavaInitializedResource class methodsFor:'documentation'!
--- a/examples/java/src/stx/libjava/examples/JavacExample.java	Wed Jan 02 16:10:35 2013 +0100
+++ b/examples/java/src/stx/libjava/examples/JavacExample.java	Wed Jan 02 18:48:11 2013 +0100
@@ -8,6 +8,13 @@
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * This example demonstrates how to use OpenJDK/Oracle javac compiler
+ * from Java. 
+ * 
+ * @author Jan Vrany
+ *
+ */
 public class JavacExample {
 
     public static void main(String[] args) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/java/src/stx/libjava/examples/JavacExample2.java	Wed Jan 02 18:48:11 2013 +0100
@@ -0,0 +1,80 @@
+package stx.libjava.examples;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.HashMap;
+
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
+import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler;
+
+import stx.libjava.tools.compiler.*;
+
+
+
+/**
+ * This example demonstrates how to use OpenJDK/Oracle javac compiler
+ * from Java. Contrary to JavacExample, in this case the source code is taken
+ * from memory. It uses stx.libjava.toosl.compiler.JavaCompilerAdapter. 
+ * 
+ * @author Jan Vrany
+ *
+ */
+public class JavacExample2 {
+	public static String source = 
+						   "public class HelloWorld {\n" +
+						   "  public static void main(String[] args) {\n" +
+						   "    System.out.println(\"Hello World\");\n" +
+						   "  }\n" +
+						   "}";
+	
+
+    public static void main(String[] args) {
+    	//JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+    	JavaCompiler compiler = new EclipseCompiler();
+    	JavaCompilerAdapter compilerAdapter = new JavaCompilerAdapter(compiler);
+    	
+    	compilerAdapter.compile("HelloWorld", source);
+    	
+    	Loader loader = new Loader();
+    	for (JavaClassFile f : compilerAdapter.getClassFiles()) {
+    		
+    		loader.getClasses().put(f.getName(), f.getBytes());
+    	}
+    
+    	try {
+	    	Class helloClass = loader.findClass("HelloWorld");
+	    	Class[] params = { String[].class };
+	    	Method main = helloClass.getMethod("main", params);
+	    	main.invoke(null, new Object[1]);
+    	} catch (Exception e) {
+    		e.printStackTrace();
+    	}
+       	
+    }
+    
+    protected static class Loader extends ClassLoader {
+    	protected Map<String, byte[]> classes = new HashMap<String, byte[]>(); 
+    	
+    	public Map<String, byte[]> getClasses() {
+    		return classes;
+    	}
+    
+    	protected Class<?> findClass(String name) throws ClassNotFoundException {       
+    		byte[] mbc = null;
+    		if (classes != null) {
+    			mbc = classes.get(name); 
+    		};       
+    		if (mbc==null){           
+    			mbc = classes.get("/" + name.replace(".","/") + ".class");           
+    			if (mbc==null){               
+    				return super.findClass(name);           
+    			}       
+    		}       
+    		return defineClass(name, mbc, 0, mbc.length);   
+    	}
+    	
+    	
+    }
+
+}
--- a/experiments/JavaCompiler.st	Wed Jan 02 16:10:35 2013 +0100
+++ b/experiments/JavaCompiler.st	Wed Jan 02 18:48:11 2013 +0100
@@ -168,17 +168,18 @@
 
 compile:source
     "Compiles a java class in given source code (passed as String).
-     Return a JavaClass which is not yet registered in Java class registry
-     nor initialiized.
+     Return an array of JavaClass which are not yet registered in Java 
+     class registry nor initialiized.
 
      To make it accessible for Java code, caller must register returned
-     class himself.
+     classes himself.
 
      Upon error, throws an exception"
 
+
     ^ self subclassResponsibility
 
-    "Modified (comment): / 15-12-2012 / 16:53:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (comment): / 02-01-2013 / 16:32:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !JavaCompiler::ClassSourceAnalyzer class methodsFor:'accessing'!
@@ -358,59 +359,30 @@
 
 compile:source
     "Compiles a java class in given source code (passed as String).
-     Return a JavaClass which is not yet registered in Java class registry
-     nor initialiized.
+     Return an array of JavaClass which are not yet registered in Java 
+     class registry nor initialiized.
 
      To make it accessible for Java code, caller must register returned
-     class himself.
+     classes himself.
 
      Upon error, throws an exception"
 
-    | javafile javac manager files units task classfile |
+
+    | javac classfiles |
 
-    javafile := self fileOut: source.
-    classfile := javafile withoutSuffix withSuffix: 'class'.
-    classfile exists ifTrue:[classfile remove].
-    javac := JAVA javax tools ToolProvider getSystemJavaCompiler.
-    manager := javac getStandardFileManager: nil with: nil with: nil.
-    files := JAVA java util ArrayList new.
-    files add: (JAVA java io File new: javafile pathName).
-    units := manager getJavaFileObjectsFromFiles: files.
-    task := javac getTask: nil with: manager with: nil with: nil with: nil with: units.
-    task call ifFalse:[
+    analyzer := self class newAnalyzer.
+    analyzer analyze: source.
+    javac := (Java classForName:'stx.libjava.tools.compiler.JavaCompilerAdapter') new.
+    (javac compile: analyzer name source: source) ifFalse:[
         self error:'Compilation failed for whatever reason!!'.
     ].
-    classfile exists ifFalse:[
-        self error:'Compilation failed for whatever reason - no class file created'.
-    ].
-    ^JavaClassReader readStream: classfile readStream.
+
+    classfiles := javac getClassFiles toArray.
+    ^classfiles collect:[:each|JavaClassReader readStream: each getBytes readStream].
 
     "Created: / 15-12-2012 / 23:04:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified: / 16-12-2012 / 15:36:16 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
-! !
-
-!JavaCompiler::Javac methodsFor:'private'!
-
-fileOut: source
-    "Files out given source into a file under JavaFileOutDirectory.
-     into proper directory (as javac requires). The directory is created
-     if it does not exists.
-
-     Returns a full filename of the filed-out source"
-
-    | analyzer filename |
-    analyzer := self class newAnalyzer.
-    analyzer analyze: source.
-    filename := JavaFileOutDirectory / 
-                    ((analyzer package ? '') copyReplaceAll:$. with: Filename separator) /
-                    (analyzer name , '.java').
-    filename directory exists ifFalse:[
-        filename directory recursiveMakeDirectory
-    ].
-    filename writingFileDo:[:f|f nextPutAll: source].
-    ^filename.
-
-    "Created: / 15-12-2012 / 23:04:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 02-01-2013 / 16:33:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !JavaCompiler::JavacExternal class methodsFor:'documentation'!
@@ -436,13 +408,14 @@
 
 compile: source
     "Compiles a java class in given source code (passed as String).
-     Return a JavaClass which is not yet registered in Java class registry
-     nor initialiized.
+     Return an array of JavaClass which are not yet registered in Java 
+     class registry nor initialiized.
 
      To make it accessible for Java code, caller must register returned
-     class himself.
+     classes himself.
 
-     Upon error, throws an exception."
+     Upon error, throws an exception"
+
 
     | classDir  wasSuccessful  package  packageAsPath  compiledClass  result |
     sourceCode := source.
@@ -455,7 +428,7 @@
     "Created: / 06-12-2012 / 23:13:47 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
     "Modified: / 07-12-2012 / 10:05:03 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
     "Modified: / 12-12-2012 / 23:58:04 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
-    "Modified (comment): / 15-12-2012 / 16:52:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (comment): / 02-01-2013 / 16:32:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 runCompiler
@@ -514,6 +487,28 @@
     "Created: / 13-12-2012 / 00:02:03 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
 !
 
+fileOut: source
+    "Files out given source into a file under JavaFileOutDirectory.
+     into proper directory (as javac requires). The directory is created
+     if it does not exists.
+
+     Returns a full filename of the filed-out source"
+
+    | analyzer filename |
+    analyzer := self class newAnalyzer.
+    analyzer analyze: source.
+    filename := JavaFileOutDirectory / 
+                    ((analyzer package ? '') copyReplaceAll:$. with: Filename separator) /
+                    (analyzer name , '.java').
+    filename directory exists ifFalse:[
+        filename directory recursiveMakeDirectory
+    ].
+    filename writingFileDo:[:f|f nextPutAll: source].
+    ^filename.
+
+    "Created: / 15-12-2012 / 23:04:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 fileOutSourceCode
     | path |
     path := sourceDir / self dotJavaPathname.
--- a/experiments/JavaCompilerTests.st	Wed Jan 02 16:10:35 2013 +0100
+++ b/experiments/JavaCompilerTests.st	Wed Jan 02 18:48:11 2013 +0100
@@ -70,6 +70,14 @@
     "Created: #testCompilingFromComplexStringWithComplexAssertions / 16-12-2012 / 15:38:56 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
 ! !
 
+!JavaCompilerTests class methodsFor:'accessing'!
+
+resources
+    ^ Array with: JavaInitializedResource
+
+    "Created: / 02-01-2013 / 15:16:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !JavaCompilerTests methodsFor:'analyzer - class name tests'!
 
 testGettingClassName
@@ -187,26 +195,27 @@
 !JavaCompilerTests methodsFor:'helpers'!
 
 registerFooBarSuperclass
-    | sourceCode  compiledClass |
+    | sourceCode  compiledClasses |
     sourceCode := '
 package stx.libjava;
 class FooBar {    
 
 }
 '.
-    compiledClass := JavaCompiler compile: sourceCode.
-    compiledClass isNil ifTrue: [
+    compiledClasses := JavaCompiler compile: sourceCode.
+    compiledClasses isNil ifTrue: [
         self 
             error: 'these tests need PackageVisibleClass and aparently it could not be compiled'
     ].
-    JavaVM registry registerClass: compiledClass.
+    JavaVM registry registerClasses: compiledClasses.
 
     "Created: / 09-12-2012 / 09:28:10 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
     "Modified: / 09-12-2012 / 20:35:03 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+    "Modified: / 02-01-2013 / 17:02:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 registerPackageVisibleClass
-    | sourceCode  compiledClass |
+    | sourceCode  compiledClasses |
     sourceCode := '
 package stx.libjava.tests;
 class PackageVisibleClass {
@@ -217,14 +226,15 @@
 
 }
 '.
-    compiledClass := JavaCompiler compile: sourceCode.
-    compiledClass isNil ifTrue: [
+    compiledClasses := JavaCompiler compile: sourceCode.
+    compiledClasses isNil ifTrue: [
         self 
             error: 'these tests need PackageVisibleClass and aparently it could not be compiled'
     ].
-    JavaVM registry registerClass: compiledClass.
+    JavaVM registry registerClasses: compiledClasses.
 
     "Created: / 08-12-2012 / 20:31:13 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+    "Modified: / 02-01-2013 / 17:02:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !JavaCompilerTests methodsFor:'tests'!
@@ -243,7 +253,7 @@
     }
 }
 '.
-    compiledClass := JavaCompiler compile: sourceCode.
+    compiledClass := (JavaCompiler compile: sourceCode) anElement.
     self assert: compiledClass notNil message: 'compiler should return compiled class'.
     self assert: compiledClass isJavaClass message: 'compiler should return java class'.
     self assert: compiledClass javaName = 'stx.libjava.tests.Wohoo' message: 'class name is not correct'.
@@ -251,10 +261,11 @@
     self assert: (compiledClass lookupMethodFor: #'foo()I') notNil message: 'compiled class should have the foo method'.
 
     "Created: / 16-12-2012 / 15:38:56 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+    "Modified: / 02-01-2013 / 16:33:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 testCompilingFromString
-    | sourceCode  compiledClass |
+    | sourceCode  compiledClasses |
     sourceCode := '
 public class Foo {
 
@@ -264,17 +275,18 @@
 
 }
 '.
-    compiledClass := JavaCompiler compile: sourceCode.
-    self assert: compiledClass notNil
+    compiledClasses := (JavaCompiler compile: sourceCode) anElement.
+    self assert: compiledClasses notNil
         message: 'compiler should return compiled class'.
-    self assert: compiledClass isJavaClass
+    self assert: compiledClasses isJavaClass
         message: 'compiler should return java class'.
 
     "Created: / 06-12-2012 / 22:59:42 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+    "Modified: / 02-01-2013 / 17:04:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 testCompilingFromStringWithImports
-    | sourceCode  compiledClass |
+    | sourceCode  compiledClasses |
     sourceCode := '
 package stx.libjava.tests;
 import org.junit.Test;
@@ -285,17 +297,18 @@
     }
 }
 '.
-    compiledClass := JavaCompiler compile: sourceCode.
-    self assert: compiledClass notNil
+    compiledClasses := (JavaCompiler compile: sourceCode) anElement.
+    self assert: compiledClasses notNil
         message: 'compiler should return compiled class'.
-    self assert: compiledClass isJavaClass
+    self assert: compiledClasses isJavaClass
         message: 'compiler should return java class'.
 
     "Created: / 08-12-2012 / 20:29:05 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+    "Modified: / 02-01-2013 / 17:05:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 testCompilingFromStringWithPackage
-    | sourceCode  compiledClass |
+    | sourceCode  compiledClasses |
     sourceCode := '
 package stx.libjava.tests;
 public class Wohoo {
@@ -305,17 +318,18 @@
     }
 }
 '.
-    compiledClass := JavaCompiler compile: sourceCode.
-    self assert: compiledClass notNil
+    compiledClasses := (JavaCompiler compile: sourceCode) anElement.
+    self assert: compiledClasses notNil
         message: 'compiler should return compiled class'.
-    self assert: compiledClass isJavaClass
+    self assert: compiledClasses isJavaClass
         message: 'compiler should return java class'.
 
     "Created: / 06-12-2012 / 23:30:54 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+    "Modified: / 02-01-2013 / 17:05:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 testCompilingFromStringWithPackageDependencies
-    | sourceCode  compiledClass |
+    | sourceCode  compiledClasses |
     self registerPackageVisibleClass.
     sourceCode := '
 package stx.libjava.tests;
@@ -326,13 +340,14 @@
     }
 }
 '.
-    compiledClass := JavaCompiler compile: sourceCode.
-    self assert: compiledClass notNil
+    compiledClasses := (JavaCompiler compile: sourceCode) anElement.
+    self assert: compiledClasses notNil
         message: 'compiler should return compiled class'.
-    self assert: compiledClass isJavaClass
+    self assert: compiledClasses isJavaClass
         message: 'compiler should return java class'.
 
     "Created: / 08-12-2012 / 20:30:05 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+    "Modified: / 02-01-2013 / 17:05:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !JavaCompilerTests class methodsFor:'documentation'!
--- a/experiments/java/src/stx/libjava/benchmarks/B1.java	Wed Jan 02 16:10:35 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-package stx.libjava.benchmarks;
-
-public class B1 {
-	
-	public int overload1(String s) {
-		return 1;
-	}
-	
-	public int overload1(Integer i) {
-		return 2;
-	}
-	
-	public int overload1(Boolean b) {
-		return 3;
-	}
-	
-	public int overload2(Object o) {
-		return 4;
-	}
-	
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/experiments/java/src/stx/libjava/tools/compiler/JavaClassFile.java	Wed Jan 02 18:48:11 2013 +0100
@@ -0,0 +1,35 @@
+package stx.libjava.tools.compiler;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import javax.tools.SimpleJavaFileObject;
+
+/**
+ * Simple in-memory representation of .class file. Used by 
+ * JavaCompilerAdapter. 
+ * 
+ * @author Jan Vrany
+ *
+ */
+public class JavaClassFile extends SimpleJavaFileObject {
+	private ByteArrayOutputStream bytes; 
+	
+	public JavaClassFile(String name) {       
+		super(URI.create("byte:///" + name + ".class"), Kind.CLASS);   
+	}   
+	public CharSequence getCharContent(boolean ignoreEncodingErrors) {       
+		throw new IllegalStateException();   
+	}   
+	public OutputStream openOutputStream() {       
+		bytes = new ByteArrayOutputStream();       
+		return bytes;   
+	}   
+	public InputStream openInputStream() {       
+		throw new IllegalStateException();   
+	}   
+	public byte[] getBytes() {       
+		return bytes.toByteArray();   
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/experiments/java/src/stx/libjava/tools/compiler/JavaClassFileManager.java	Wed Jan 02 18:48:11 2013 +0100
@@ -0,0 +1,32 @@
+package stx.libjava.tools.compiler;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.io.IOException;
+
+import javax.tools.FileObject;
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+public class JavaClassFileManager extends ForwardingJavaFileManager {
+	protected Map<String, JavaClassFile> classes = new HashMap<String, JavaClassFile>();
+	
+	public JavaClassFileManager(StandardJavaFileManager sjfm) {       
+		super(sjfm);  		
+		   
+	}   
+	public JavaFileObject getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject sibling) throws IOException {       
+		JavaClassFile mbc = new JavaClassFile(name);       
+		classes.put(name, mbc);       
+		return mbc;   
+	}
+
+	public ClassLoader getClassLoader(Location location) {       
+		return null;   
+	}
+	
+	public Map<String, JavaClassFile> getClasses() {
+		return classes;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/experiments/java/src/stx/libjava/tools/compiler/JavaCompilerAdapter.java	Wed Jan 02 18:48:11 2013 +0100
@@ -0,0 +1,56 @@
+package stx.libjava.tools.compiler;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
+
+/**
+ * Simple Java compiler adapter to compile classes completely in memory. 
+ * @author Jan Vrany
+ *
+ */
+public class JavaCompilerAdapter {
+	protected List<String> options = Collections.emptyList();
+	protected JavaCompiler compiler;
+	protected JavaClassFileManager classFileManager;
+	
+	public JavaCompilerAdapter() {
+		this(ToolProvider.getSystemJavaCompiler());
+	}
+	
+	public JavaCompilerAdapter(JavaCompiler compiler) {
+		this.setCompiler(compiler);
+	}
+	
+	
+	
+	public void setCompiler(JavaCompiler compiler) {
+		this.compiler = compiler;
+		this.classFileManager = new JavaClassFileManager(compiler.getStandardFileManager(null, null, null));
+	}
+	
+	public Collection<JavaClassFile> getClassFiles() {
+		return classFileManager.getClasses().values();
+	}
+	
+	/**
+	 * Compiles classes in given source. The resulting .class files are added
+	 * to an internal list which can be later retrieved by getClassFiles().
+	 * 
+	 * @param name unqualified name of class being compiled. 
+	 * @param source source code of the class as String.   
+	 * @return true, if compilation succeeded, false otherwise.
+	 */
+	
+	public boolean compile(String name, String source) {
+		List units = Arrays.asList(new JavaSourceFile(name, source));		
+		JavaCompiler.CompilationTask task = compiler.getTask(new PrintWriter(System.err), classFileManager, null, options, null, units);
+		return task.call();
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/experiments/java/src/stx/libjava/tools/compiler/JavaSourceFile.java	Wed Jan 02 18:48:11 2013 +0100
@@ -0,0 +1,33 @@
+/**
+ * 
+ */
+package stx.libjava.tools.compiler;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import javax.tools.SimpleJavaFileObject;
+
+
+/**
+ * @author Jan Vrany
+ *
+ */
+public class JavaSourceFile extends SimpleJavaFileObject {
+	private String src;   
+	
+	public JavaSourceFile(String name, String src) {       
+		super(URI.create("file:///" + name + ".java"), Kind.SOURCE);       
+		this.src = src;  
+	}   
+	public CharSequence getCharContent(boolean ignoreEncodingErrors) {       
+		return src;   
+	}   
+	public OutputStream openOutputStream() {       
+		throw new IllegalStateException();   
+	}   
+	public InputStream openInputStream() {       
+		return new ByteArrayInputStream(src.getBytes());   
+	}
+}
--- a/tools/java/src/stx/libjava/tools/SyntaxHighlighter.java	Wed Jan 02 16:10:35 2013 +0100
+++ b/tools/java/src/stx/libjava/tools/SyntaxHighlighter.java	Wed Jan 02 18:48:11 2013 +0100
@@ -1,15 +1,17 @@
 package stx.libjava.tools;
 
-import java.util.ArrayList;
-
 import org.eclipse.jdt.core.dom.*;
 
+/**
+ * A syntax highlighter using eclipse DOM. Replaced by Petit-parser based
+ * highligher. 
+ * 
+ * @author Jan Vrany
+ *
+ */
 public class SyntaxHighlighter extends ASTVisitor {
 	protected SyntaxHighlighterHandler handler;
 	
-	protected ArrayList l;
-	
-
 	public SyntaxHighlighter(SyntaxHighlighterHandler handler) {
 		this.handler = handler;
 	}
--- a/tools/java/src/stx/libjava/tools/tests/SyntaxHighlighterTests.java	Wed Jan 02 16:10:35 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-package stx.libjava.tools.tests;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.ArrayList;
-
-import org.junit.Test;
-
-import stx.libjava.tools.SyntaxHighlighter;
-import stx.libjava.tools.SyntaxHighlighterHandler;
-
-public class SyntaxHighlighterTests {
-
-    public class Handler implements SyntaxHighlighterHandler {
-
-        public ArrayList<String> marks = new ArrayList<String>();
-
-        @Override
-        public void markString(int startPosition, int length) {
-            marks.add("string-" + startPosition + "-" + length);
-        }
-
-        @Override
-        public void markComment(int startPosition, int length) {
-            marks.add("comment-" + startPosition + "-" + length);
-        }
-
-        @Override
-        public void markConstant(int startPosition, int length) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void markKeyword(int startPosition, int length) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void markClassName(int startPosition, int length) {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    @Test
-    public void test_01() {
-        Handler handler = new Handler();
-        SyntaxHighlighter highlighter = new SyntaxHighlighter(handler);
-        highlighter.formatExpression("\"a\" + \"b\"");
-
-        assertEquals(2, handler.marks.size());
-        assertEquals("string-0-3", handler.marks.get(0));
-        assertEquals("string-6-3", handler.marks.get(1));
-
-    }
-
-    @Test
-    public void test_02() {
-        Handler handler = new Handler();
-        SyntaxHighlighter highlighter = new SyntaxHighlighter(handler);
-        highlighter.formatExpression("1+1/* xxx */");
-
-        assertEquals(1, handler.marks.size());
-        assertEquals("string-4-9", handler.marks.get(0));
-
-    }
-}