Friday, March 21, 2008

(Grease) Monkey Business

I've been reading David Byrne's journal (of the Talking Heads fame) since before I heard about blogs and blogging. In an ocean of software blogs that flood my Google Reader, it's one of the few that remind me that I have other interests besides computers. From this journal I found out that he also hosts an internet radio station that I've been often enjoying while at work or sometimes at home.

For this task I've been using iTunes on my Mac at home and Rhythmbox on Linux at work. Besides the easier subscription to the station, the one thing I miss from iTunes while at work is seeing the currently playing song on Rhythmbox. I don't know how iTunes does it, but it's always showing the correct song title and artist, while on Rhythmbox all I see is the station name.



Therefore I had resorted to having a tab open in Firefox all day that displayed the radio home page that shows the playlist and refreshes each time a new song begins. I still had to switch to the browser from whatever I was doing when a new song started, in order to glance on its title and performer. A few days ago I thought to myself: "wouldn't it be nice to have the Firefox title bar display that information and only take my eyes off what I'm currently doing and not my fingers too?".


It turns out that I'm very persuasive when I'm talking to myself, so I set off to make my wish come true. I've been also trying to find an excuse to learn more about Greasemonkey for some time and it seemed like the right time to do it. So after I spent some time reading up stuff from the web, I came up with something that made me happy:


(function() {
window.addEventListener("load", function(e) {

var PLAYLIST_URL = 'http://www.live365.com/pls/front?handler=playlist&cmd=view&viewType=xml&handle=todomundo&maxEntries=1';

(function fetchCurrentSong() {
GM_xmlhttpRequest({
method: "GET",
url: PLAYLIST_URL,
onload: function(details) {
var xmlString = details.responseText;
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xmlString, "application/xml");
var refresh = xmlDoc.getElementsByTagName('Refresh')[0].textContent;
var artist = xmlDoc.getElementsByTagName('Artist')[0].textContent;
var album = xmlDoc.getElementsByTagName('Album')[0].textContent;
var title = xmlDoc.getElementsByTagName('Title')[0].textContent;
var label = title+' by '+artist+' from '+album;
document.title = label;
setTimeout(fetchCurrentSong, refresh);
}
});
})();

}, false);
})();


It's amazing what 20 lines of JavaScript can do. You can install this user script by clicking here, assuming you have Greasemonkey installed and enabled. If you don't have Greasemonkey or prefer to install a firefox extension that does not require it, click this link instead. It was automagically created with the very nifty User Script Compiler.

This is what I see now when I'm listening to David's playlist (although many times I just glance at the title in the minimized button on the bottom panel):


Remixing the web, indeed.

Wednesday, March 19, 2008

Re: I wish I could...

I can tell that spring is here, when my friend George tags me with another blog meme. Apparently it's like a ritual to him, but it came a few weeks earlier this year, so I figured I could delay posting at least until last year's anniversary. With the frequency I blog, he doesn't have much to expect anyway.

This year's theme is to write about crazy or stupid things you'd like to do, but can't, or stupid things that you do anyway. Since I'm running an old-fashioned, respectable blog here, I'll restrict my answer to appropriate stuff, namely computers and software. And with that I expect to have lost 50% of my audience, so I guess that leaves me and you George. So without further ado, here are 10 things (in no particular order) I wish I could do, but probably won't:

  1. ...stop reading FreeBSD mailing lists.
  2. ...convince my colleagues at work to switch to Mercurial for version control.
  3. ...transfer a call at work (in a Linksys IP Phone) without loosing it.
  4. ...build the zero-administration appliance I was planning.
  5. ...use and contribute to JNode, an operating system written in Java.
  6. ...write a book about a computer-related subject.
  7. ...implement class data sharing for 64 bit VMs.
  8. ...write Objective-C code using Xcode.
  9. ...stop subscribing to more blogs and even ditch a few altogether.
  10. ...blog more often.
I guess I'm not that ambitious after all...

Saturday, March 15, 2008

How to create a WebDAV interface in 10 easy steps


Test Driven Development (TDD) is all the rage these days. And rightly so, if you ask me. Compare developing software against constantly changing client requirements and developing against a specification in the form of tests that your code must pass. I've done my share of the former for the better part of the last 9 years and I've got the gray hair to prove it. However, I only got a chance to practice the latter very recently and I must say I'm hooked.

My TDD endeavor concerns a small project to add a WebDAV interface to an existing server-side code base. The system already featured other interfaces for manipulating the resources stored in it, but a cross-platform, standards-based, nicely integrated, native client was deemed necessary. Enter WebDAV, a.k.a. HTTP on steroids. Most desktop systems nowadays have a WebDAV client installed by default (Windows calls it Web Folders, others prefer not to rename it), so testing a WebDAV server is not that complicated: if you can mount, browse, store and retrieve files and folders using your desktop client, the server implementation is fine. Nevertheless, we can do better than that. Using litmus, a "WebDAV server protocol compliance suite", we can make sure that our implementation respects the protocol, even in its more obscure corner cases and more importantly, perform the testing automatically, without painstaking clickety-click.

Implementing a WebDAV interface from scratch by reading the protocol specification is not the easiest nor the smartest path. You will have to read it in order to figure out what goes where, but you could also reuse some parts from an existing implementation. If you are extending an existing Java codebase, like me, your best bet is reusing the Tomcat implementation. You can run the litmus suite against a vanilla Tomcat installation, just to verify its WebDAV functionality. Not all tests pass, since the implementation is incomplete, but don't worry, most clients don't implement the spec completely either. However take a note of the results, since this is your target outcome.

For your own convenience, I have described the whole development process in 10 easy steps, ready to print, free of charge, batteries not included:

  1. Download the litmus test suite.
  2. Download the sources for Tomcat, particularly WebdavServlet.java and DefaultServlet.java.
  3. Create your own version of WebdavServlet that will delegate the actual functionality to your own backend and fill it with empty stub methods that correspond to the ones in Tomcat.
  4. Build & deploy your server.
  5. Run the litmus test. All tests fail the first time, but when it eventually succeeds (i.e. matches the result of vanilla tomcat), go to step 9.
  6. Fill one method at a time from Tomcat's sources, substituting the JNDI communications with your backend logic.
  7. Add any other helper methods from other Tomcat classes as necessary.
  8. Go to step 4.
  9. Most tests succeeded, so you are done!
  10. For extra credit: fix the code to pass some more tests and send your changes upstream.
You are bound to come across some hair-splitting problems when modifying the codebase to fit in you own backend, but it beats writing it all from scratch hands down, unless you are Greg Stein or Jim Whitehead. In my case, after two weeks and a submitted patch, I was done and had the tests to prove it. Furthermore, when the need for a code refactoring arises, I can rest assured that my changes won't break the protocol functionality if the litmus tests still pass. Not to mention that I have now contributed to Tomcat.

Man, I haven't felt that good in ages.

Creative Commons License Unless otherwise expressly stated, all original material in this weblog is licensed under a Creative Commons Attribution 3.0 License.