Weekly Snap: Averting Java Plugins, Playing with HTML 5 & Hooks

30 Jan – 3 Feb turned over a new month with expo reflections, an OSDC program, and a nifty Java idea for Icinga/Nagios plugins – all topped off with our 100th development blog post.
Bernd brought home a few impressions from his visit to the Cloud Expo Europe in London and Lennart found a way around writing Java plugins for Icinga / Nagios.
From the development team, Angsar toyed with the idea of programming games in HTML5 while Marius showed how to add hooks in Perl to make patching vendor code a little easier.
Pamela closed the Open Source Data Center conference Call for Papers, and announced the preliminary program of speakers. She also reminded early birds to get in before  15 February for special conference rates.

Bitte einhängen!

Software funktioniert immer und ist ausschließlich ohne Bugs. Falls nicht ist sowieso immer der Vendor schuld. Der hat allerdings gerade keine Zeit und damit dauert es bis zur nächsten Bug-Fix Release.
Auch kein Problem, immerhin ist das Produkt kostenlos und der Quellcode offen, aber Hersteller Code ändern? Wenn in der Software selber keine Hook Konzepte oder Factories vorgesehen sind ist man nicht mehr Update-Fähig. Patches passen nicht mehr auf die neue Version und müssen mühsam angepasst werden oder man hat die Dokumentation verlegt oder erst gar keine angelegt.
Unter Perl gibt es ein paar Interessante Konzepte, Hooks nachträglich anzulegen. Eine davon ist Hook::WrapSub, welche Aufruferketten mit eigenen Prozeduren verbindet.
Folgendes Beispiel:

#!/usr/bin/perl -w
package TEST_SCRIPT::BINARY;
use version 1.0;
use strict;
use subs qw(do_something);
sub do_something {
        my ($first, $last) = @_;
        return sprintf('My name is %s, %s', $last, $first);
}
print do_something('Eduart', 'Zimmermann');
print "\n";
exit(0);

Ein Aufruf brachte folgendes Ergebnis:

$ perl test_script.pl
My name is Zimmermann, Eduart

Wir bräuchten nun eine Änderung in der Funktion ‘do_something‘ ohne den eigentlich Code zu verändern und verbauen eine Aufruferkette in einem eigenen Module:

package HookThat;
our $VERSION='1.0';
use Hook::WrapSub;
use Data::Dumper;
Hook::WrapSub::wrap_subs
        sub {
                splice @_, 0, 1, $_[0]. '-Hubert';
        },
        'TEST_SCRIPT::BINARY::do_something',
        sub {
                $Hook::WrapSub::result[0] =~ s/My name is/I am the holy/;
        };
1;

Dieses Modul binden wir in den bisherigen Code ein. Das bleibt die einzige Änderung. Eventuell gibt die Software Möglichkeiten vor, eigene Module in die Ausführung zu laden. Dann benötigt man überhaupt keine Änderungen am Quelltext mehr. Außerdem, alle eigenen Anpassungen in einem Module zu organisieren erleichtert eine spätere Wartung deutlich.

$ diff -u test_script.pl  test_script_neu.pl
--- test_script.pl	2012-02-02 15:27:12.476374490 +0100
+++ test_script_neu.pl	2012-02-02 15:30:58.388368456 +0100
@@ -4,6 +4,7 @@
 use strict;
 use subs qw(do_something);
+require 'HookThat.pm';
 sub do_something {
 	my ($first, $last) = @_;

Die Ausgabe ändert sich durch unseren Hook folgendermaßen:

$ perl test_script.pl
I am the holy Zimmermann, Eduart-Hubert

Die Funktion ‘wrap_subs‘ erweitert den Aufruf von ‘do_something‘ durch einen Pre- und einen Postwrapper. In der ersten Prozedur ändern wir das Argument des Vornamens und verändern in der zweiten (bzw. letzten) den ersten Satzteil. Es lassen sich dadurch auch komplexe Ketten gestalten um die Software passend für den jeweiligen Einsatzzweck fit zu machen, z.B. Mailverarbeitung zu generalisieren oder ‘eigentlich’ interne Datenquellen durch Fremdsysteme (DB, Soap) zu befüllen ohne die Boardmittel der Anwendung zu verändern.
Für Perl gibt es noch weitere Module die mehr oder minder den selben Zweck erfüllen, Hook::LexWrap sei hier noch zu nennen, welches allerdings in der aktuellen Version keine Änderung der Argumente zulässt (Und dadurch fast schon wieder völlig unbrauchbar ist). Auch den Weg ‘zu Fuß’ gibt es natürlich (“Perl Symbol Table Hackery”):

*_Foo = *Foo;
*Foo = sub { print "Doing something different\n"; };

Alle diese Möglichkeiten sind zwar nicht besonders Simple und Perl erhöht nicht gerade die Leserlichkeit. Beim nächsten Update hält sich der Frust aber deutlich in Grenzen und die Anpassungen sind schnell wieder aktiv – Kaffeetrinken – Fertig!
Achso, dies ist übrigens der hundertste (ja, 100) Dev-Blogpost – Tättärätäääää! Vielen Dank an alle im Development für all die Gedanken, Zeilen und Worte im Schweiße des Angesichts ausformuliert …

Marius Hein
Marius Hein
Head of Development

Marius Hein ist schon seit 2003 bei NETWAYS. Er hat hier seine Ausbildung zum Fachinformatiker absolviert, dann als Application Developer gearbeitet und ist nun Leiter der Softwareentwicklung. Ausserdem ist er Mitglied im Icinga Team und verantwortet dort das Icinga Web.