JaninoWhat is Janino? Here is the description from the Janino homepage: Janino is a compiler that reads a JavaTM expression, block, class body, source file or a set of source files, and generates JavaTM bytecode that is loaded and executed directly. Janino is not intended to be a development tool, but an embedded compiler for run-time compilation purposes, e.g. expression evaluators or "server pages" engines like JSP. Although Janino comes with some examples it is not so obvious how to embed it into your own application. That's why I put together two examples which should help you doing that. Example 1: compiling from filesThe first example is a simple getting startet example: package org.svenehrke.example.janino.command; import org.codehaus.janino.JavaSourceClassLoader; import org.codehaus.janino.DebuggingInformation; import java.io.File; public class JavaSourceClassLoaderExample { public static void main(String[] args) throws Exception { new JavaSourceClassLoaderExample().execute(); } private void execute() throws Exception { File janinoSourceDirs = new File("janino-src"); File[] srcDirs = new File[]{janinoSourceDirs}; String encoding = null; ClassLoader parentClassLoader = getClass().getClassLoader(); ClassLoader cl = new JavaSourceClassLoader(parentClassLoader, srcDirs, encoding, DebuggingInformation.NONE); Command xc = (Command) cl.loadClass("org.example.svenehrke.janino.command.MyCommand").newInstance(); xc.execute(); } }
package org.svenehrke.example.janino.command; public interface Command { public void execute(); } package org.example.svenehrke.janino.command; import org.svenehrke.example.janino.command.Command; public class MyCommand implements Command { public void execute() { System.out.println("MyCommand.execute(): hello from janino"); } }
Just to give you a hint on what you can do with this: Try to put the code
above in an endless loop so that
By the way: if you decide use this in you work and want to leverage the power
of your IDE for the Java text files (under the folder Example 2: compiling from arbitrary resources
In some situation you would rather not use the filesystem as a source
for these dynamic Java source files because you might want to read them
from jar files for example or generally from the classpath. This is a bit
more complicated because you need to write your own package org.svenehrke.example.janino.command; import org.codehaus.janino.JavaSourceClassLoader; import org.codehaus.janino.DebuggingInformation; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.apache.commons.io.IOUtils; import java.util.Map; import java.util.HashMap; import java.io.StringWriter; import java.io.IOException; public class JavaSourceClassLoaderFromMapExample { public static void main(String[] args) throws Exception { new JavaSourceClassLoaderFromMapExample().execute(); } private static final String CLASSNAME = "org/example/svenehrke/janino/command/MyCommand"; private void execute() throws Exception { String dotClassName = CLASSNAME.replace('/', '.'); Resource resource = getResource(); try { byte[] ba = byteArrayFromResource(resource); Map map = new HashMap(); map.put(CLASSNAME , ba); MapResourceFinder mrf = new MapResourceFinder(map); ClassLoader parentClassLoader = JavaSourceClassLoaderFromMapExample.class.getClassLoader(); String encoding = null; ClassLoader cl = new JavaSourceClassLoader(parentClassLoader, mrf, encoding, DebuggingInformation.ALL); Command cmd = (Command) cl.loadClass(dotClassName).newInstance(); cmd.execute(); } catch (Exception e) { throw new RuntimeException(e); } } private byte[] byteArrayFromResource(Resource aResource) throws IOException { StringWriter sw = new StringWriter(8192); IOUtils.copy(aResource.getInputStream(), sw); return sw.toString().getBytes(); } private Resource getResource() { return new FileSystemResource("janino-src/org/example/svenehrke/janino/command/MyCommand.java"); } }
The idea is to load the Java source code as byte array from an arbitrary
resource, put it under a key in a
Here some more detailed explanation: routine package org.svenehrke.example.janino.command; import org.codehaus.janino.util.resource.Resource; import org.codehaus.janino.util.resource.ResourceFinder; import java.io.IOException; import java.io.InputStream; import java.io.ByteArrayInputStream; import java.util.Map; public class MapResourceFinder extends ResourceFinder { private final Map map; private long lastModified = 0L; public MapResourceFinder(Map map) { this.map = map; } public void setLastModified(long lastModified) { this.lastModified = lastModified; } public final Resource findResource(final String resourceName) { int p = resourceName.indexOf(".java"); final String s = resourceName.substring(0, p); final byte[] ba = (byte[]) this.map.get(s); if (ba == null) return null; return new Resource() { public InputStream open() throws IOException { return new ByteArrayInputStream(ba); } public String getFileName() { return s; } public long lastModified() { return MapResourceFinder.this.lastModified; } }; } } |