2007-12-29

MD5 in Java


MD5 (Message-Digest Algorithm 5) ist eine weit verbreitete, von Ronald L. Rivest entwickelte kryptographische Hash-Funktion. Sie erzeugt einen 128-Bit-Hashwert, der meistens als Folge von 16 (zweistelligen) Hexadezimalzahlen angegeben wird. Solche Werte (Hashes oder message digests) werden unter anderem zur Integritätsprüfung von Dateien eingesetzt.
Erwartungsgemäß gibt es Implementierungen für unzählige Sprachen. Java bietet seit Version 1.4 nativen Support in Form der Klasse java.security.MessageDigest .
Ich habe eine kleine Wrapperklasse geschrieben, die das Ermitteln von Digests ermöglicht. Um sie einzusetzen, müssen Sie die Klasse nur instantiieren und getChecksum() aufrufen. Da diese Methode ein byte-Array liefert, können Sie mittels toString() noch einen schön lesbaren String erzeugen.

2007-12-22

Fullscreen-Plug-in für Eclipse


Bei der Arbeit mit einer IDE kann man eigentlich nie genug Platz auf dem Bildschirm haben. Gerade Eclipse bietet unzählige Sichten an, die dem Entwickler beim Programmieren helfen sollen. Mit Hilfe des Eclipse Full Screen Plugins können Sie die Taskleiste sowie die Fenstertitelzeile ausblenden und Eclipse in einem Vollbildschirm-Modus betreiben. Leider steht das Plug-in derzeit nur in einer Version für Windows zur Verfügung.

2007-12-18

Defensives Programmieren


In meinem heutigen Eintrag möchte ich mich mit dem Thema Defensives Programmieren beschäftigen. Wenn Sie den Begriff (oder seine englische Entsprechung defensive programming) in das Eingabefeld der Suchmaschine Ihres Vertrauens eintragen, werden Sie sehr schnell entsprechende Wikipedia-Seiten finden. Die momentan aktuelle (nachgeschlagen am 18.12.2007) deutsche Fassung enthält eine aus meiner Sicht leider nur eingeschränkt tragfähige (weil unvollständige) Definition. Der Eintrag beschreibt nämlich (völlig zu Recht), was aus fachlicher Sicht zu tun ist, um angemessen auf Fehleingaben oder unvorhergesehene Ereignisse zu reagieren. Er lässt technische Belange aber nahezu vollständig außen vor.
Defensive Programmierung lässt sich jedoch nicht auf Bevor Du einen Drucker löscht, prüfe, ob er dem System überhaupt noch bekannt ist. reduzieren. Neben dieser fachlich motivierten Robustheit spielt die Qualität des Quelltextes eine entscheidende Rolle. Sie äußert sich unter anderem in seiner kompromisslosen Toleranz gegenüber Fehlern von innen und außen, getreu dem Motto Traue Nichts und Niemandem. Diesem Aspekt trägt die englische Fassung übrigens viel mehr Rechnung.
Welche Auswirkungen hat ein solcher Programmierstil? Flapsig ausgedrückt könnte man sagen, Sie müssen die Paranoia zum Maß aller Dinge machen. Da jeder Methodenaufruf fehlschlagen oder eine Ausnahme werfen kann, ist es unabdingbar, nicht nur sauber alle Rückgabewerte zu verarbeiten, sondern auch mit unerwarteten Exceptions zu rechnen. Denken Sie daran, dass in Java nicht nur dann eine Ausnahme geworfen werden kann, wenn dies mit throws explizit gekennzeichnet wird. Bitte sehen Sie sich die folgende kleine Klasse an.
   
package com.thomaskuenneth.demo;
   
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
   
public class BadFileDemo {
   
public static void main(String[] args) {
File f = new File(System.getProperty("user.home"), "BadFileDemo.txt");
try {
FileOutputStream fos = new FileOutputStream(f);
fos.write("Test\n".getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
   
Auf den ersten Blick scheint es sich um ein recht ordentlich geschriebenes Stück Software zu handeln. Oder? Lassen Sie uns sehen, wie man es ein bisschen besser machen kann…
   
package com.thomaskuenneth.demo;
   
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
   
public class BetterFileDemo {
   
public static void main(String[] args) throws IOException {
File f = new File(System.getProperty("user.home", "."),
"BadFileDemo.txt");
if ((f.exists() == true) && (f.isDirectory() == true)) {
throw new IOException(f.getAbsolutePath()
+ " exists and is a directory");
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);
fos.write("Test\n".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
fos = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
   
Haben Sie die Unterschiede bemerkt? Oder, anders gefragt, was sind denn die gröbsten Schnitzer im ersten Programm? Diese zweite Klasse wirkt zugegeben um einiges länger. Schuld daran ist der neue finally {}-Block, der um einiges sorgfältiger beim Schließen des Ausgabestroms zu Werke geht. Falls Sie sich fragen, ob der Aufwand nötig ist… Aber logo. Warum sollte diese Aktion nicht fehlschlagen können? Außerdem wird so ein großes Manko beseitigt. Wenn im ersten Programm während des Schreibens in den Strom ein Fehler auftritt, wird er nicht geschlossen. Nicht schön, nicht wahr? :-)
Ein weiterer, subtiler Schutz ist übrigens noch dazu gekommen. Finden Sie ihn?

2007-12-11

Vom sicheren Umgang mit Eclipse-Plug-ins


Dass sich der Funktionsumfang von Eclipse durch Plug-ins erweitern lässt, wird sehr oft als eine Schlüsselfunktion der IDE angesehen. Und mit Hilfe des Software Updates-Mechanismus geht das Ganze ja auch sehr bequem und komfortabel über die Bühne. Zumindest, wenn das Plug-in über eine Remote Site installiert werden kann.
Nun gibt es aber (immer noch) sehr viele (sehr gute) Plug-ins, die als .zip-Archiv verteilt werden. Nach dem Entpacken landen sie dann (etwas vorschnell) im Eclipse-Installationsverzeichnis. Mein Rat ist, sie stattdessen in einem eigenen Verzeichnis abzulegen. Gründe hierfür gibt es zahlreiche. Beispielsweise mischen Sie auf diese Weise nicht die Eclipse-Distribution mit Plug-ins von Drittanbietern. Wenn sie die IDE neu einrichten müssen, bleiben die zusätzlichen Plug-ins davon unberührt.
Bevor Sie die neue "Modulablage" Eclipse bekannt machen können, müssen Sie sie von Hand anlegen und präparieren. Legen Sie hierzu bitte ein Verzeichnis mit beliebigen Namen an, beispielsweise C:\Programme\Eclipse Plug-ins. In diesem erzeugen Sie bitte das Unterverzeichnis eclipse, das wiederum die beiden Verzeichnisse features und plugins enthält. In einem letzten Schritt legen Sie die leere Datei .eclipseextension an.
Wählen Sie nun Software Updates • Manage Configuration, woraufhin sich das Fenster Product Configuration öffnet. Klicken Sie anschließend mit der rechten Maustaste die Wurzel des Konfigurationsbaumes an und wählen dann Add • Extension Location.
Mit Hilfe der Dateiauswahlbox navigieren Sie zu dem Verzeichnis, das die Plug-ins aufnehmen soll. Bevor Sie der IDE den gewünschten Neustart gestatten, kopieren Sie das Plug-in in das neue Verzeichnis.