Tuesday, December 04, 2007

genpet

24-year old Canadian commercial artist Adam Brandejs has fooled me too with his latest atrwork, the genpets! Genpets are supposed to be the creation of Bio-Genica, by combining and modifying existing DNA, and are portrayed as real living pre-packaged, mass produced, bioengineered pets, with blood, bones, muscle, who will bleed if you cut them and die if mistreated. You may find all about his creation on his site, together with the what, why and how. The main point of Genpets is to get the public thinking about the concept of bioengineering. Previous works of art included the flesh shoe and the animatronic heart.

Saturday, December 01, 2007

gpg

I have used GnuPG, the most well-known open-source implementation of OpenPGP standard, to create my public key in PGP ascii-armoured format (RFC2440):

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.7 (MingW32) - GPGshell v3.63

mQGiBEdJwaoRBACGOLGMcEZvvVoLILK/u8MlEttmZgriE/kh/J4KU7Vq1X2aPqYO
IL19VtHKRzQLpk9sAJK51tUbdDRQAm7A0nkkgHZYFfTLY1a9UYUamx3xgtqQ/aWf
kdeqazc2iOv1WcfaDZruLq5I6CY1BB+naUnlDw1q/4icxBaXy5cATGG/4wCghlVQ
fjutAS44UD/w9WpMWAFiUT8D/ijZI1aoyNzHt1pPgJzu63Q8mOM/5WLXtvIFhseN
Yn5jHQBbZvbz/qLN+A04TOS6ZJeiOb7u3sBinM5HxtwFsL/8R7fX9KDtv/0XeCpC
jJxrkhid3Xa6PdVku121RarbXCVjU2J/emsfM7+M5KzkAMqttCVlOQ1B10wxaKoJ
h37jA/9tY8KfDURirg0MIByMVXqeAy/pjB7y+VbTUynzGOXzjMvpFSXeq5mUQrQa
5wfD6g/bsqREQRgSgRi/5zdQJ3kTwAC/9ia1V37iRDVMcWd177t+NnkMuHh/EQRr
BRFyh6Ahw+uE+DYGzipHrTjbzIbmbx9lprK0a0qc5rp5SJhvj7Q7VmFzc2lsaXMg
TWljaGFsaXRzaXMgKEdQRyBwdWJsaWMga2V5KSA8em1lZWFnYWluQGdtYWlsLmNv
bT6IYAQTEQIAIAUCR0nBqgIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEApn
iDzXc29ZJrwAn35i7EU/sOhGyMd2qWdYLhXLn0NPAJ4s7yy2FivfsFs3zOppzF/S
mF7qybkCDQRHScGqEAgAsLjOBlN54y75Vkjkj/Gw0X6vy0nj1SZtQDTef8ZF2oYQ
FX0+KgiR+v9Jgu39GTO6adWwga8DXBHwx+72yMiKh7mnd1p2ppuaGzUos0Vj0WJt
lnPXmpmjahWc5NEO/svWEU1OaNPp70OqY3y7k72PmWZU1CGvw+CBe2herFf+1R5T
or6sq31xfuGLW6MSwj2Tf00SeezK0lVZSOfrVHjWj5VQ6cevExEexWi6idU29Hrk
MZ8JfIEE3qPcPBX30s2NrzLU24eFVczv3CRNsGHUdNAsauwpkheycnMvrdGE7yBo
hkEQ08FROsp/RkbcqbKCczoW09Qc+kVr0SDsidLRDwADBQf/folYqDxqrzmGc2vQ
FisWIWMaPp6P602vtTr6CkICEpuWs10aCQCvHWyhS9rv0/ycbPV9F/HLT9JPAwD3
G60wuzzLbqTlFVxhzSORmmN92t0Xe0tBJa7TbuCJ6j5WfdvskopCC2BGhNJnxZbD
gBjrWGOE+dOJY7B/W8NyPerfcS7RIk5YtwP3uIfPiBwSf+75ToiquXqUkFlnA+LY
6aVyr6KHDk/OuV4rKZJdu8JikZkK5H48v9UK/k5WTQPQJhOP7QdfQa70/yz+Zksb
XgyF8YIgFjUKxcHexh2+wWsbeK4A53XdtyY+JFLApZFywE7u+DZQ721PYTMKVYb+
GpxvaYhJBBgRAgAJBQJHScGqAhsMAAoJEApniDzXc29ZQJsAn0MkgLNZOocsb8KZ
0W6yyu1yP4xDAJ41P01c3jmDH/2sNN/+xbjOaF38lg==
=JM2U
-----END PGP PUBLIC KEY BLOCK-----

You may find it in MIT's public PGP key server and as if that weren't enough, it can also be found here, here, here, here, and here. To import it into your keyring save it in a text file, say zmeeagainpk.asc, and then type:
gpg --import zmeeagainpk.asc
gpg: key D7736F59: public key "Vassilis Michalitsis (GPG public key) <zmeeagain@gmail.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1
As an example let's take the following snippet of text:

The Armor Headers are pairs of strings that can give the user or the receiving OpenPGP implementation some information about how to decode or use the message. The Armor Headers are a part of the armour, not a part of the message, and hence are not protected by any signatures applied to the message.

I have clear signed it using my PGP key and the result is:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

The Armor Headers are pairs of strings that can give the user or the receiving OpenPGP implementation some information about how to decode or use the message.  The Armor Headers are a part of the armor, not a part of the message, and hence are not protected by any signatures applied to the message.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (MingW32) - GPGshell v3.63

iD8DBQFHUrdQCmeIPNdzb1kRAksZAJ0cOJSKNwkkGmTyQDR4sf39Kl5XgQCffsCu
HpMVh4lnKcq0xmKvc9XA7IU=
=TFRB
-----END PGP SIGNATURE-----

To verify the signature, select this clear signed text, including the armour headers, and save it as signed-text.txt. Then type
gpg --verify signed-text.txt
gpg: Signature made 12/02/07 15:46:56 using DSA key ID D7736F59
gpg: Good signature from "Vassilis Michalitsis (GPG public key) <zmeeagain@gmail.com>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 426B D59A 9798 E07A 88F8  9647 0A67 883C D773 6F59
Notice that GPG complains that the signing key may not belong to the actual owner. You have to add the newly imported public key to your trusted keys, i.e. the keys you know they come from who they were supposed to, by signing it with your own key:
gpg --edit-key D7736F59

pub  1024D/D7736F59  created: 2007-11-25  expires: never       usage: SC
                     trust: unknown       validity: unknown
sub  2048g/61B55FAD  created: 2007-11-25  expires: never       usage: E
[ unknown] (1). Vassilis Michalitsis (GPG public key) <zmeeagain@gmail.com>
Command> sign

pub  1024D/D7736F59  created: 2007-11-25  expires: never       usage: SC
                     trust: unknown       validity: unknown
 Primary key fingerprint: 426B D59A 9798 E07A 88F8  9647 0A67 883C D773 6F59

     Vassilis Michalitsis (GPG public key) <zmeeagain@gmail.com>

Are you sure that you want to sign this key with your
key "..." (...)

Really sign? (y/N) y

You need a passphrase to unlock the secret key for
user: "..."
... key, ID ..., created ...
Verifying signed-text.txt should not display a warning anymore:
gpg --verify signed-text.txt
gpg: Signature made 12/02/07 15:46:56 using DSA key ID D7736F59
gpg: Good signature from "Vassilis Michalitsis (GPG public key) <zmeeagain@gmail.com>"
Among the various GPG GUIs GPGShell is perhaps the most comprehensive and it is the one I am using for the examples here.

Friday, November 23, 2007

disqus

I decided to give Disqus a try and replace Blogger's default commenting system. I have kept a copy of my old template just in case, as Disqus is very much in beta version right now. Not that I get a lot of comments anyway...

Monday, November 05, 2007

concurrency

An awesome book on concurrency that all Java programmers ought to read before embarking on anything more complicated than the primordial Hello World application. I cannot help but reiterate here an example on one of my favourite subjects, that of publication safety. A typical (yet unsafe) lazy initialisation is shown below:


public class LazyInitialization {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null)
            resource = new Resource();
        return resource;
    }
}
There's two issues with this approach. The first is easy to spot: if threads A and B call getInstance() at the same time, they may both see resource as null and both proceed in creating a Resource instance, hence ending up creating two different instances even though getInstance() is supposed to always return the one and the same instance.

The second is much more subtle and has to do with publication. Suppose that thread A first invokes getInstance() and creates a Resource instance, then thread B sees that resource is non-null and returns the resource reference. B could observe however the write to the resource reference by A as occurring before writes to resource's fields by Resource's constructors! Hence, B could see a partially constructed Resource. One way this can be fixed is by making getInstance() synchronized. Another way is by changing the lazy initialization to eager:


public class LazyInitialization {
    private static Resource resource = new Resource();

    public static Resource getInstance() {
        return resource;
    }
}
Why does this work? Static initializers are run by JVM at class initialization time, i.e. before any thread has the chance to use the class. In addition, JVM acquires a lock while doing so, and this same lock is acquired by every thread at least once to ensure that the class has been loaded, therefore all memory writes made during initialization are visible to all threads. Any subsequent modifications will need to be synchronized of course between readers and writers, unless Resource is immutable.

Saturday, October 20, 2007

picnik

Picnik IS the best online photo editor around. Simple, intuitive, rich, blazing fast. I was very glad to hear that Flickr will incorporate picnik's amazing functionality for photo editing. At last I shall be able to make my Flickr sets look more presentable.

Thursday, August 23, 2007

FindBugs

Inspired by Josh Bloch and Bill Pugh's Java Puzzlers talk at Google, Java Puzzlers, episode VI, I decided to use FindBugs and analyze some core Java libraries we wrote and used at one of my previous employments. Here are some of the findings: Commons: 675 classes, 505 bugs (98 bad practice, 27 correctness, 96 malicious code vulnerability, 14 multithreaded correctness, 207 performance, 63 dodgy). Messaging: 31 classes, 21 bugs (9 bad practice, 8 malicious code vulnerability, 3 performance, 1 dodgy) Services: 239 classes, 78 bugs (5 bad practice, 4 correctness, 35 malicious code vulnerability, 1 multithreaded correctness, 26 performance, 7 dodgy) Content management: 637 classes, 577 bugs (38 bad practice, 14 correctness, 72 malicious code vulnerability, 3 multithreaded correctness, 382 performance, 68 dodgy)

Example bugs include:

Bad attemnpt to compute absolute value of signed 32-bit hashcode:

indexPrimary +=  Math.abs(this.getStoragePrimary()
  .hashCode()) + SEP;
Why? If the hash code is equal to Integer.minValue() then the result will be negative as well.

Impossible cast (ouch!):

ArrayList list=new ArrayList();
setChoices((DateDatum[])list.toArray());
Possible null reference dereference for internalConnetion:
try {
  if(internalConnetion == null) {
    throw new TransactionManagerException("...");
  }
  ...
  } catch(Exception e) {
    throw new TransactionManagerException(
      e.getMessage(), e);
  } finally {
    if (internalConnetion.getDepth() < 1) {
Nullcheck of value previously dereferenced:
if (accountId.equals(internalAccount)) {
  permissions.add(new AllPermission());
  return permissions;
}
if (accountId == null) {
  return permissions;
}
This last comparison for null is redundant since, if true, it would have already raised an exception.

Method invokes inefficient Boolean constructor:

return new Boolean(false);
Boolean objects are immutable, there's no need to create a new instance; use Boolean.valueOf(...) instead.

Method invokes inefficient new String(String) constructor:

String path = new String("");
Method concatenates strings using + in a loop:
for(int i = 0; i < (hash.length / 2); i++) {
  rtnValue += Integer.toHexString(x);
}
Inefficient use of keySet iterator instead of entrySet iterator:
Set keySet = headers.keySet();
Iterator iterator = keySet.iterator();
while(iterator.hasNext()) {
  String value = (String) headers.get(key);
}
May expose internal representation by incorporating reference to mutable object:
public void setMethods(Hashtable methods) {
  this.methods = methods;
  FunctionsContainer.getLogger().info("Loaded " +
    methods.size()+" methods");
}

This code stores a reference to an externally mutable methods object into the internal representation of the object. Storing a copy of the object would have been much safer.

It's always a good idea to statically analyse your code once you're done with it. It's not going to render it bug free but it certainly helps. Oh, and while I'm at it, go get yourself a copy of Java Puzzlers book; it helps avoiding some very dark corners you might not have been aware of.

Sunday, August 19, 2007

xkcd

A webcomic of romance, sarcasm, math, and language by Randall Munroe. Check it.

Friday, August 17, 2007

parkour


I didn't know that parkour was so popular until I saw the video above. This is a short definition from Wikipedia:

Parkour (sometimes abbreviated to PK) or l'art du déplacement (English: the art of displacement) is recreational activity of French origin, the aim of which is to move from point A to point B as efficiently and quickly as possible, using principally the abilities of the human body.

Astonishing eh? Now my traceurs, summon your spidery powers and displace yourselves!

Tuesday, August 14, 2007

cURL

If you are not already using it, I suggest you start using cURL. cURL, or Client for URLs, or see URL comes in two flavours, a command line tool for getting and sending files using URL syntax and a library, libcurl, for use by other programs. It supports more than a dozen protocols (FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP), cookies, proxy tunneling, transfer resume, authentication (Basic, Digest, NTLM, Negotiate, kerberos...), SSL certificates, HTTP uploads, progress meter, speed limit, you name it. Here's some examples:

Upload a file as multipart/form-data plus extra params to a URL: curl -F upload=@localfilename -F press=OK [URL]

Use an agent of your choice: curl -A "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)" [URL]

Get the last 500 bytes of a document: curl -r -500 http://www.get.this/

ftp upload through a proxy: curl --proxytunnel -x proxy:port -T localfile ftp.upload.com

Read and write cookies from a netscape cookie file: curl -b cookies.txt -c cookies.txt www.example.com

Download resume: curl -C - -o file http://www.server.com/

cURL is in Flash Player 9, Mac OS X, F-Secure and IBM's BOINC among others. Interfaces exist for most major as well as other more obscure languages. Unfortunately, the javacurl interface supports a small subset of cURL's features and is not well tested.

Friday, August 10, 2007

cloning adventure

Once I wanted to create clones of tree nodes, naming the clones of node say A as A-Copy-1, A-Copy-2, etc. My first thought was using the parent's child-count property and start counting copies from that value onwards. However, if the nodes are A, A-Copy-1 and A-Copy-2, when A-Copy-1 gets deleted the child-count becomes 2 and if that is used you get the same name as one of the existing children. Then I thought I would simply iterate through all children named A-Copy-i, for i = 1 to child-count, and create clones whenever that name was for take. That would reuse slots created by previous deletions but would make distinguishing the new nodes impossible. This was easily fixed by finding the maximum copy count of A and start creating clones after that so, if A-Copy-4 and A-Copy-6 sibling nodes are left in the tree, any new copies would be named as A-Copy-7, A-Copy-8 etc. That way you would always get a nice continuous set of cloned nodes in the tree. Even if you wanted to clone A-Copy-i node, that would quite naturally become A-Copy-i-Copy-j. I decided to use regular expressions to look for <node name>-Copy-<copy count> sibling nodes. That gave the extra benefit of having the copy count part available by means of a capturing group. To force any metacharacters in the node name to be treated like ordinary characters, I preceded every single character in the name with backslashes:

StringBuffer escapedNodeName = 
  new StringBuffer(nodeName.length()*2);
for (int i = 0; i < nodeName.length(); i++) {
  escapedNodeName.append('\\').append(nodeName.charAt(i));
}
RE exp = new RE(escapedNodeName.toString() + "-Copy-([1-9]\\d*$)");
This failed miserably! Guessed why? It is quite alright to escape a metacharacter, but it is another kettle of fish when "escaping" ordinary characters. When this code was used on a tree which had numbers in names, the escaped digits became backreferences and the match failed. I hastily changed the escaping part of the code to enclose the name within a quote (\Q and \E). No sooner had I done this than I realised that even that had its own fallacy: what if the node name had a \E in it? Proper quoting required some more effort:
StringBuilder escapedNodeName = 
  new StringBuilder(nodeName.length() * 2);
escapedNodeName.append("\\Q");
slashEIndex = 0;
int current = 0;
while ((slashEIndex = nodeName.indexOf("\\E", current)) != -1) {
  escapedNodeName.append(nodeName.substring(current, 
                                            slashEIndex));
  current = slashEIndex + 2;
  escapedNodeName.append("\\E\\\\E\\Q");
}
escapedNodeName.append(nodeName.substring(current, 
                                          nodeName.length()));
escapedNodeName.append("\\E");
Thankfully this is made available as java.util.regex.Pattern.quote(String) method since Java 1.5.

Tuesday, July 31, 2007

freemarker vs velocity

There is a feature comparison sheet on Freemarker site, listing why Freemarker is a superior templating engine to Velocity. Not very objective you may say, but there are certain features, like the use of JSP tags and XML transformation capabilities that Velocity lacks. Freemarker more closely follows the MVC pattern, in that Velocity allows you to change the model from the view (e.g. request.session.removeAttribute(attrName) will remove the attribute) while Freemarker does not let you do so. I do not think that any of the two engines is a serious contender for a full blown web engine to be honest, but I would be interested to see some speed statistics, especially for uses in high volume messaging applications where every single message would need to go through the engine. Furthermore, the quest for separation of the model from the view reminds me of that other quest for over-validation. I don't want templates that change my model, sure, but I don't want to have to recompile my classes just because an email wants person.surname in addition to person.name in it, either.

Friday, July 13, 2007

alfresco

There's been an interesting development in the area of Enterprise Content Management (ECM) space during the last couple of years, that goes by the name Alfresco. I've been meaning to write about it for quite some time when I got tickled again by one recent email of theirs, announcing the release of Alfresco Community 2.1. For those of you not familiar with it who still think that ECM is all about boring apps organizing boring docs made by boring cos, think again. Alfresco is open source based on best-of-breed technologies, including Spring, Hibernate, Lucene, jBPM, MyFaces, Rhino etc and providing a rich set of interfaces like CIFS/SMB, FTP, WebDAV, Web Services, REST. It was started in 2005 by John Newton co-founder of Documentum and John Powell, former COO of Business Objects and has since been downloaded some 600,000 times and installed at more than 12,000 sites and going strong. I wonder what the implications will be on the likes of IBM (FileNet), Interwoven and Oracle.

Wednesday, July 11, 2007

life is beautiful

Here's an idea: after the usual spam checks, pass every incoming email automatically through Snopes, as a last resort to spam prevention. These emails are hard to detect as the senders have usually added their very own personal comment, and most of the time they are among your trusted friends. Therefore, you not only stumble upon the email in your inbox instead of it being automatically thrown to your trash can, you are fooled by the sender into actually opening and reading the email before you realise it is yet another hoax. Worse still, you have to go manually through Snopes, just in case it is real. Life is beautiful is one of these hoaxes that was first circulated on the Internet back in 2002 and got sent to me again... today.

Wednesday, July 04, 2007

bumptop

Vista has surely spiced up things a bit, as far as user interfaces go, and Mac's new Leopard is really beautiful. But how about rethinking the whole desktop and the ways one can interact with it? Anand Agarawala has done exactly that, with BumpTop, a physically-based, casual user interface that pushes the desktop metaphor with physics, piles and the pen. For the more inclined, Anand's Masters Thesis (Enriching the Desktop Metaphor with Physics, Piles and the Pen) and a paper co-authored with Ravin Balakrishnan say it all.

Monday, June 04, 2007

alpha, beta, gamma, loves you, delta

We all know the various software development cycles. Alpha used to be mostly for internal testing. Beta represented versions released to the wider public for the purpose of real world testing. Nobody dared call their version Gamma out of fear that people would confuse that with their Gamma Phi Beta sorority. So most stuck to Beta, using enumerations to denote post-Beta releases like Beta I (or 1), Beta II (or 2) etc. Then Microsoft figured that an operating system was entitled to a brand new concept of post-Beta test cycles and, that system being Windows, they probably were right. So they started issuing what they euphemistically called Release Candidate versions to the public. Of course, you could always find some very peculiar versioning conventions if you looked hard enough, like Knuth's TeX ever approaching Pi numbers. By the time open source software became de facto, and releases were mostly Web Server software updates, Release Candidate sounded too formal and rigorous, so Gamma became the new Beta II. Now Flickr calls one of its recent releases "LOVES YOU", instead of Delta, Gamma II, Super/Post Candidate Release I, signalling a new era of version naming standard. Who knows what the next release will be? WILL MARRY YOU perhaps.

Wednesday, March 21, 2007

trendalyzer

Google recently acquired the Sweden-based Gapminder, the "non-profit venture for development and provision of free software that visualise human development", makers of the amazing Trendalyzer®. Not many people have heard of them up until now, but the visualization and real-time interaction possibilities are just mind blowing. Have a look at this demo. Now I know what you must be thinking: how can I have something like that in my webapp? I'm afraid you'll have to resort to good old jfree chart.

Friday, March 09, 2007

get humanized

I recently came across Humanized, a company that tries to bring the command line to the common man, by exposing operating system or application operations as simple commands, that can be typed at any time. For example, by holding down [Ctrl] and typing "open with" or a part of it, it will automatically open whatever has been selected with the application of your choice. This is part their Enso Launcher application, the other one being Enso Words. Enso Words lets you do all kind of things you would normally do from within a word processor through the humanized command line, from spell checking to word counting. A pleasant change.

Friday, February 09, 2007

Microsoft/AOL giveaway

Not really. This is an old internet hoax, dating back in 2004, claiming that Microsoft and AOL are running a tracked email test paying people for participating, urging them to forward a silly . Now, why am I making such a fuss NOW, many years after this hoax first appeared? Because there are gullible people out there that keep circulating these phony messages believe or not, and they did send it to me!!!!
Well, sorry folks, but there aint no free lunch yet. Now get back to work.