Usage

To get this library to work, you have to execute your program using a JDK. The library itself does not have any additional requirements.

If you want to launch arbitrary uncompiled code without writing your own subsystem, you can use the provided launcher. The launcher requires the executed code to have a public static void main(String[] args) method which does not throw.

It is required to provide all additional 3rd party dependencies used in the code to be compiled on the classpath. Otherwise the class cannot be compiled or launched.

To use the launcher execute:

java -cp <path-to-runtime-compiler-lib.jar>:<path-to-additional-jars-required-by-compiled-file> com.github.hypfvieh.java.rtcompiler.RtCompilerRunner <File-To-Compile> <arguments passed to compiled file>

All additional arguments provided to the call will be passed to the static main of the compiled class.

The Launcher will return different exit codes when something went wrong with compilation:

Code Meaning
0 Everything went fine
200 No or empty arguments
201 No Java source file name given or file does not exist
203 Compilation error in Java source file
204 No valid main method in source file
205 Run-time exception encountered in execution of source file
206 Checked exception encountered in execution of source file

Additional information are logged using the logging framework (if any) or logged to stderr.

Add the library to your project:

    <dependency>
        <groupId>com.github.hypfvieh.java</groupId>
        <artifactId>runtime-compiler-lib</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>

Now you can use the library like this:

    private SomeClassInstance createClassInstance() {
        File myFile = new File("path/to/file/MyClass.java");
        Class<?> fileCreator = JavaFileLoader.createClassFromFile(myFile.getAbsolutePath());
        Object javaObjFromFile = fileCreator.getDeclaredConstructor().newInstance();

        if (!(javaObjFromFile instanceof SomeClassInstance)) {
            throw new ClassCastException(String.format("Source %s is not a subclass of %s", myFile, SomeClassInstance.class.getName()));
        }

        return (SomeClassInstance) javaObjFromFile;
    }

This will look for a file ‘MyClass.java’ in ‘path/to/file/’ and will compile it. After that it will try to call the default no-args constructor and casts it. The class SomeClassInstance is extended by the source in ‘MyClass.java’ so it is possible to return a more concrete class type instead of Object.

The library will take care about compiling and also tries to find all classes imported directly or through inheritance by the compiled source.

It is possible to use inheritance of sources which also have to be compiled. E.g. when ClassB extends ClassA, RuTiCo will try to compile ClassB which fails. Due to the errors created by the compiler RuTiCo will try to find ClassA using the compiler error. After compiling ClassA the failed compilation of ClassB is retried.