Sending Growls from a remote host

There are times when I want a notification about the status of a long running process I have running on a remote system. I could have it send an email. I could have it send an instant message. I decided that, since I have a Mac, I would have it send a Growl notification. Growl's GNTP makes this easy and the language bindings available make it easier still.

The one obstacle I had was getting the IP address of the connecting host (i.e., my Mac). Commands like finger and who often show this data but I did not want to scrape the command output as it is different between operating systems. Digging into the code for who at koders.com I discovered that it used the user accounting database utmpx API for getting this data. And so, with all the parts needed, I coded up growler

#!/usr/bin/perl -w

use strict;
use Getopt::Long;
use Growl::GNTP;
use User::Utmp qw(:constants :utmpx);

sub getRemoteHost() {
my @utmp =
sort { $b->{ut_time} <=> $a->{ut_time} } # reverse sort by time
grep { $_->{ut_user} eq getlogin() } # filter by current user
getutx(); # get user accounting data
( my $host = $utmp[0]->{ut_host} ) =~ s/:.*$//;
return $host;
}

my $title = "";
my $host = getRemoteHost();
my $port = 23053;

GetOptions(
'title|t=s' => \$title,
'host|h=s' => \$host,
'port|p=i' => \$port )
or do {
print STDERR "usage: $0 ",
" [ --title text ]",
" [ --host name/ip ]",
" [ --port number ]",
" message\n";
exit(1);
};

my $growl = Growl::GNTP->new(
AppName => "growler",
PeerHost => $host,
PeerPort => $port
);

$growl->register([ { Name => "growler" } ]);

$growl->notify(
Event => "growler",
Title => $title,
Message => join( ' ', @ARGV )
);

# END

My original installation of Growl was broken. This caused all manner of errors during testing. To finally get growler to work I had to uninstall Growl and then install Growl 1.4.

Refactoring Java classes with explicit serialVersionUIDs

I had a small problem today where I needed to refactor a Java class and maintain its serialization identity. I guessed that if I maintained the class's instance variable order and explicitly defined the serialVersionUID class variable with the class's previous implicit value I would be safe. So, before refactoring, I used Java's serialver to get the class's serialVersionUID. I then refactored the class and added the serialVersionUID class variable. But it didn't work. What was wrong? I needed to look into the object's serialization.

An object's serialized form is defined in Java Object Serialization Specification. I really didn't want to read the specification: All that I really wanted was to see the differences between the class's pre-refactor stream and the post-refactor stream. So I used jdeserialize to dump the protocol encoding of the streams.

What was quickly apparent in the dump was that the order of the instance variables within the stream have no relation to their order in the class definition. I was not expecting this. During the refactoring I had renamed some instance variables to better reflect their purpose. Once I reverted the instance variable's names to their previous values the serialization was the same. Success.

A distressing aspect of this exploration was that two objects with the same serialVersionUID will be considered the same by the serialization implementation and so it will misinterpret the bytes in the stream for the bytes needed by the class. The end result is that you get an object that is initialized wrong. I would have expected an exception that indicated the mismatch between data in the stream and data expected by the class. Perhaps there is a command line switch or system property I can use to enforce a stricter pairing. Be very careful when refactoring a class with an explicit serialVersionUID to either remove or update its value before committing the changes.


The trifecta of low-ceremony document management

My comment on How I name files on my Mac:
I too add dates to file names even though I know the creation date is part of the file's meta-data. When files are moved between systems the meta-data is not always preserved. This chance of loss is also what thwart me from using a tagging tool as I can not be assured that the tags will be preserved between systems. And so, the trifecta of low-ceremony document management are
  • a good title,
  • a date in the title, and
  • a good full-text search.

I want more "geek lights"

Geek-lights are the indicator lights embedded on the surface of your electrical equipment. The green "On" light. The blinking light on your ethernet port or USB thumb-drive telling you data is being transferred. Most of them tell you redundant or otherwise obvious facts. I don't need an "on" light for the monitor I am using. It is useful information when in power saving mode, however. Apple seems to have learned this.


However, geek-lights are incredibly useful for other kinds of information. Information that is different for you and me. For example, one to indicate if traffic is too heavy to venture out now. Another to tell me that I have email. Another to tell others that I am in a conference call and not just talking to myself again.

I would like to have a box of these geek-lights that I can use each for a specific purpose. The geek-light would be nothing more than a shallow and wide cylinder with the light on the top, temporary adhesive on the bottom, and the electronics sandwiched in between. Let's call them eyelets as they let you see something ordinarily invisible. Each eyelet is individually addressable by a short range wireless signal. An eyelet receives a signal that indicates whether it is illuminated or not. Eyelets don't send signals back. I can imagine the hardware being something akin to Logitech's Unifying receiver -- that is, unobtrusive.

The question now is, should eyelets have a battery charge indicator light?


"Acting like a startup" is overrated

"Anyone who isn't acting like a startup in publishing [replace with your industry] has a serious problem." I hate this aphorisms. It is not useful and mostly wrong. The only difference between a new product at a startup and one at an established company is where the seed money comes from. Everything else is the same.