Ever wonder what all the fighting is about?
On the one hand, we have Java, with it's basis in object-oriented theory, automatic memory management, dependency on a runtime, and a robust library. And on the other, we have Microsoft.NET, with it's basis in object-oriented theory, automatic memory management, dependency on a runtime, and a robust library.
You'd think with all these two kids have in common, they would get along better. No such luck.
Up until now, getting Java to talk to Microsoft.NET has been only slightly more fun than being on the receiving end of a root canal. One book I picked up recently was all about interoperability using Web Services. Web Services! Not that there is anything wrong with Web Services in general, but I why do I need a web server, WSDL, and the overhead of two-way XML serialization if I just want a list of the processes on my local system (something Java cannot do)?
Maybe you've tried something like passing data to a spawned process using standard-input and standard-output. It's limited, but it works. You still need something like SOAP or XStream if you want to work with objects, and at least you don't have the overhead of a full blown web server. But it's still not simple. Or maybe you've tried using sockets. Same thing, but without incurring the overhead of starting and stopping a process every time you need to do something that is windows-ey. Still, that's not simple.
You are probably thinking, "There must be a better way." And that would make sense, because you took the time to read the title of this article, correct? I am here to tell you - there is a better way. In fact, I am here to tell you, it's easy.
Microsoft's Component Object Model (COM)
Microsoft spent decades developing this technology called COM. It stands for Component Object Model. "Wait a second," you say. "Isn't COM dead? Doesn't .NET make it obsolete?" You might think so, but look how long .NET has been around, and Microsoft Office is still compiled from plain old ANSI C++. Consider also that the .NET libraries for Microsoft Office are thin wrappers around the COM libraries that Office exposes. COM is embedded deeply in Windows, it is mature, stable, and it's not going anywhere.
Microsoft.NET has excellent support for COM interoperability. You can create and consume managed COM libraries using VB.NET, C#, or C++/CLI. It's almost trivial to do so in VB.NET, for example. You just set a few properties, build the project, and you've got a COM-callable DLL.
So if COM is there, it's mature, it's stable over decades, and it works for what you are doing, why not just use it?
Groovy and Scriptom
Groovy, for those who aren't already familiar with it, is a very cool dynamic language that is designed specifically to run on the Java JVM. The syntax is based on Java, and everything gets compiled to Java bytecode. Java programmers have an easy learning curve, and Groovy can be integrated seamlessly into existing Java projects. Groovy is a lot more expressive than Java, so you can typically get things done in about half the lines of code. And once you get used to it, Groovy is easier to read than Java.
Scriptom is an optional module for Groovy that lets you use COM objects. Scriptom takes advantage of Groovy's dynamic (late-bound) nature to map COM objects into Groovy objects at run-time. There are no type-libraries to deal with and no wrappers to maintain. Just code it and run it. It really is a lot like writing code using VBScript (except that Groovy is far more advanced as a language), and it is almost eerie at times to see Java comingled with what appears to be something straight out of WSH (Windows Script Host). Thus, the name - "Script-om."
Let's Do Something!
Create a COM-Accessible VB.NET Library
Step 1. Create a New Project
Open Visual Studio and create a new VB class library project called MyFips140Crypto.
Step 2. Add the Code
Rename Class1 to SHA and add the following code:
Step 3. Enable COM
To enable COM support, open the project properties and click the Assembly Info button. Fill in the dialog any way you want, but make sure that Make assembly COM-Visible is checked.
Step 4. Give It a Strong Name
What is a "strong name," you ask? Well, it is some sort of Microsoft security cryptographic digital signature thingy. Why do you care? In most cases, you won't. The important thing to remember is that you won't be able to successfully register the library later without this.
Lucky for us, Microsoft has made this step relatively easy. From the project properties page, you can have Visual Studio create a new strong name key file for you. You can optionally protect the key file with a password.
Once the strong name key file is associated with your project, you generally don't have to worry about it again.
Step 5. Build It
Build the project.
Step 6. Register It
Open Visual Studio 2005 Command Prompt. It is one of the tools that comes standard with Visual Studio. Navigate to the folder where your compiled DLL is going to reside, and type in the following command:
If you have been lucky enough to get everything right so far, you'll get a confirmation message telling you that the assembly was registered successfully. Congratulations!
Okay, that was tough. There are a couple of not-so-obvious steps involved in creating even a simple COM-enabled .NET library. Fortunately, once you know all the steps, it is pretty much just following the same recipe. And once you have set up a .NET project this way, it is easy to add another class.
You might expect that for the Groovy portion of this project, there is a similar type of overhead incurred. You'd be wrong though. With Groovy, it is more like scripting. Here is all the code you need to compute the SHA-1 hash of an arbitrary string:
There you have it. A FIPS 140-1 approved SHA-1 implementation in about 20 lines of code. Enjoy!
NEED TO PUT IN a section for Groovy integration in Java.
I don't know where this part is going...
So think about this for a second. This code is converting a Java String to a COM String supporting unicode. The COM String is converted to a .NET-compatible String. .NET converts the String to an array of bytes and passes it to a standard .NET Framework object that then calls the Microsoft CryptoAPI to generate a 160-bit hash code. The result is passed back from the CryptoAPI into .NET and converted to a COM array. That array is passed back to Groovy as a SafeArray, which is converted to a Java byte array.
And all you had to do was write a couple of lines of code on each end.