While writing this entry I'll try not to turn it in to just another long dig at Domino, but it might end up going that way. Sorry.
I'm writing a CAPTCHA plugin for a Domino site at the moment. Although I've managed to get a working solution I can't help but feel it could have been a whole lot easier to achieve were there not a couple of things missing from the basic toolkit of a Domino developer.
Creating images on the fly using Java Agents is actually a lot easier than you might think. The hard part -- at least with Domino -- is getting the resulting image to the browser.
There are several Java libraries out there for creating CAPTCHAS but they all seemed huge to me and just a little OTT. Not only that but the two or three I looked at (including the most popular JCaptcha seem to rely on you having such a thing as a user "session" that ties separate page requests together. We don't in Domino and so can't use them unless we're willing to suffer writing and deploying servlets (something I'd leave to the very end until I went down that route).
After further searching I found the source to a JSP page where somebody had written a CAPTCHA generator in less than 100 lines of code. That's what I like to see. Lean and to the point.
Not that is was a simple case of copy/paste of course. The code was written using parts of Java, such as ImageIO, which were only introduced in Java 1.4. My target was a Domino 6 server, which only has Java 1.3 (Domino 7 has Java 1.4).
After more searching I found you could write JPEG files using an undocumented package called com.sun.image.codec.jpeg in Java 1.3. The trouble here though is that there's no way to write the JPG file you've produced directly to the browser.
The main way a Java Agent writes to the browser is using the PrintWriter class, but this won't let you work with files and their inner bytes. Just text! Mikkel Heisterberg has written about this limitation on his well-worth-reading blog. He found that there's an undocumented method in Domino 7's Java called "getAgentOutputStream()" which gives us an OutputStream object. This is exactly what we need. The trouble is it's buggy and unusable. Whether it works in Domino 8 or not I don't know?
The only real way (although I hope somebody is going to correct me on this) to get the image to the browser is to save it to the server's disk first!
Saving to the server's disk is easily done and isn't a big deal, as long as you clean up after yourself, but I'd prefer to avoid that in the first place. Not only because it means you have to make sure code is signed with IDs that are allowed to run unrestriced code and the Agent itself needs to have an increased level of access, but it also means you have to make sure the Agent never gets updated by a copy signed with another ID, which would break the code. It's really quite messy.
Why, why, why can't we create an OutputStream in a Domino Java Agent!?