Wednesday, 11 September 2013

Running Groovy natively in .NET using IKVM

I’m really getting into Groovy (see also Programming Eclipse in Real-Time (using an 'Groovy based' Eclipse Plug-in)), but one problem is that Groovy runs natively on the JVM!

And although I could use Jni4Net to create a bridge between a JVM and the CLR, it would be much nicer if I could write Groovy scripts under the CLR (with live access the FluentSharp APIs and O2 created objects).

And by using IKVM I was able to do exactly that :)

I was able to convert the main Groovy jar JVM bytecode into .NET CLR bytecode, and evaluate Groovy scripts directly in C# (i.e. without a JVM loaded in the current process). For more O2 usage of the amazing IKVM API's see Util - O2 Java Tools (IKVM Based) v1.0 


Evaluating an Groovy script in .NET:

After created the groovy-all-2.1.6.dll .Net IKVM dll (see Appendix 1) Creating groovy-all-2.1.6.dll below), I was able to consume it (in O2’s C# REPL) like this:

image

The screenshot above is quite an amazing achievement, since what we have there is the pure .NET execution of the “40 + 2”  groovy script :)

For example here is a new instance of the Java ProcessBuilder object (created outside an Java based JVM)

image

Which can be used in Groovy-style to start calc:

image

And for an even more interesting example, the line 4 of the script below

image

... will open the GroovyConsole, which is a Swing application running under the CLR!!!

image

From here we can execute groovy scripts, like this one:

image

... like this (with an error):

image

… or like this:

image

Next thing to try is if are able to access .NET Apis from this Groovy environment.

Using the UI described in Appendix 2) Creating a simple Groovy REPL UI (see below) here is how to access MSCorLib.dll apis from the Groovy Java scripting environment:

image

For that to work we need first to create the mscorlib.jar so that the ‘CLR-based JVM’ can find the clr.System.IO.* classes (see IKVM’s Develop a .NET Application in Java  article for more details)

This is done using the command: ikvmstub -out:dlls/mscorlib.jar mscorlib which will create the respective mscorlib.jar

image

Next let’s access some of FluentSharp APIs.

As with mscorlib, we start by creating the FluentSharp.CoreLib.jar using ikvmstub -out:dlls/FluentSharp.CoreLib.jar -r:C:\Windows\assembly\GAC_MSIL\
\System.Core.dll  E:\O2\_Source_Code\FluentSharp\FluentSharp.O2Platform\bin\Debug\FluentSharp.CoreLib.dll 
(note the extra reference to System.Core.dll)

image

We can then consume the fluentSharp.CoreLib.jar like this:

image

Since FluentSharp.CoreLib.dll had more dependencies, I used this script:

//var topPanel = "{name}".popupWindow(700,400);
var ikvmFolder = @"C:\Users\o2\AppData\Roaming\OWASP_O2_Platform_5.3\_ToolsOrApis\IKVM\ikvm-7.2.4630.5\bin";
var targetJar = ikvmFolder.pathCombine(@"dlls\FluentSharp.WinForms.jar");
var ikvmStub = ikvmFolder.pathCombine("ikvmstub.exe");
var arguments = "-out:\"{0}\" ".format(targetJar) + 
                @" -r:C:\Windows\assembly\GAC_MSIL\System.Core\3.5.0.0__b77a5c561934e089\System.Core.dll" + 
                @" -r:C:\Windows\assembly\GAC_MSIL\System.Xml.Linq\3.5.0.0__b77a5c561934e089\System.Xml.Linq.dll" +
                 " \"{0}\"".format("FluentSharp.WinForms.dll".assembly_Location());
                 
return ikvmStub.startProcess_getConsoleOut(arguments);        

Which created the FluentSharp.WinForms.jar file:

image

Here is how to get a class to one of FluentSharp extension methods helper classes:

image

... and here is how to invoke it:

image

ok, the code above (using the Extension Method static invocation) it is not as user friendly as the normal FluentSharp code:

      "This is a Groovy Form".popupWindow() 

....but with a couple custom groovy builders, we should get there :)


(the rest of this post contains the 2 appendixes referenced above)



Appendix #1: Creating groovy-all-2.1.6.dll

Similar to the process described at Running Groovy on .NET 2.0 using IKVM  and Groovy running fine on .NET (both posted in 2007) I wrote this O2 Installer script:

image

... which uses the (already existing) IKVM API to create the dll:

image

Once that installer executes (with a bunch of warnings shown on the log viewer), we have the desired groovy-all-2.1.6.dll file created (which is a .NET version of the Java jar file):

image



Appendix 2) Creating a simple Groovy REPL UI

There are already a number of FluentSharp APIs that allow the easy creation of REPL UIs. For example:

image

... which can be easily extended to support the groovy evaluate capabilities

image

... and looks like this when executed:

image

... and like this (after making it a popupWindow)

image

After saving this script as Util - Simple Groovy Shell.h2

image

... we can execute it as a normal O2 tool:

image

Note how the groovy Binging object is holding the objects created during multiple executions (i.e. the calc variable was set during the first execution (shown above)):

image