I have now seen several projects ending at a point where the actual configuration depended on things only available at run-time.
The typical way to configure a Java prog
Try SISC, it is a reasonably small (300kb jar) Scheme implementation with no bells and whistles. Glueing it with Java is trivial, and an execution speed is quite impressive for a pure interpreter.
I know you want a small size and runtime. Scheme is the usual choice for easy embedding, and would be my first choice. But I have no information on that field, though. My second choice is Clojure:
A respective code with using Clojure:
import clojure.lang.RT;
import clojure.lang.Var;
import clojure.lang.Compiler;
import java.io.FileReader;
import java.io.FileNotFoundException;
public class ClojTest {
public static void main(String[] args) throws Exception {
try {
Compiler.load(new FileReader("hello.clj"));
} catch(FileNotFoundException e) { return; }
System.out.println("Message: '"+ RT.var("user", "msg").get() +"'");
// Values
int answer = (Integer) RT.var("user", "answer").get();
// Function calls
System.out.println(RT.var("user", "countdown").invoke(42));
}
}
with hello.clj
being:
(ns user)
(defn countdown [n]
(reduce + (range 1 (inc n))))
(def msg "Hello from Clojure!")
(def answer (countdown 42))
Running time java ClojTest
for a while yields in an average of 0.75 seconds. Clojure compiling the script has quite a penalty!
Good, much smaller solution is an embedded Scheme for Java. Out of many implementations, I found and tested JScheme. (API looks okay: http://jscheme.sourceforge.net/jscheme/doc/api/index.html)
A simple main program in Java:
import jscheme.JScheme;
import jscheme.SchemeException;
import java.io.*;
public class SchemeTest {
public static void main(String[] args) {
JScheme js = null;
try {
js = new JScheme();
js.load(new FileReader("config.scm"));
} catch (FileNotFoundException e) { return; }
System.out.println("Message: '" + js.eval("msg") + "'");
// Values
int answer = (Integer) js.eval("answer");
// Function calls
System.out.println(js.call("countdown", 42));
}
}
And an example config.scm
:
(define (countdown x)
(define (loop x acc)
(if (= x 0)
acc
(loop (- x 1) (+ acc x))))
(loop x 0))
;;; config variables
(define msg "Hello from JScheme!")
;; tail calls are optimized as required
(define answer (countdown 42))
The scheme is being interpreted at startup every time, so this is good choice for configurations. Advantages to JScheme include:
Benchmark update: this code runs in 0.13 seconds time. Compared to the Clojure version's time this is pretty fast.
Clojure is excellent, it is embeddable and has very good interoperability for calling Java libraries. However it is not particularly small (you get a full compiler and quite a decent runtime library included). Still worth considering if you have a broader requirement for this kind of functionality - I've found Clojure to work as an excellent dynamic "glue" for Java code.
Otherwise, your best bet is probably a tiny embedded Scheme interpreter.
It may be possible to use the early (1998) version of JScheme at this link, which is only about a 30k jar file: http://norvig.com/jscheme.html
Otherwise, it's probably possible to write something even more minimal in a few hundred lines of Java.... it's probably only a weekend project considering how small the core of Scheme is. The following page is quite interesting if you want to write a mini-interpreter for Scheme: http://archives.evergreen.edu/webpages/curricular/2000-2001/fofc00/eval.html