It's amazing how the more things change, the more they remain the same. On the one hand, we have Java, with it's basis in object-oriented theory, automatic memory management, and dependency on a runtime and a robust library that abstracts the system it runs on. And on the other hand, we have Microsoft.NET, with it's basis in object-oriented theory, automatic memory management, and dependency on a runtime and a robust library that abstracts the system it runs on.
You'd think with all these two kids have in common, they would get along better. No such luck.
Getting Java to talk to Microsoft.NET is 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 natively).
Maybe you've tried something like passing data to a 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, it can get complicated.
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.
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 written in unmanaged C++. Consider also that all 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.
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, so it's very easy for us Java programmers to work with. Groovy is a lot more expressive than Java, so you can typically get things done in about half the lines of code. And I've found I can read through Groovy code a lot faster.
Scriptom is Groovy module that lets you consume COM objects.
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!
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.