Einsatz des Data Warehouse SuperX und Realisierung mobiler

Werbung
Einsatz des Data Warehouse SuperX
und Realisierung mobiler Szenarien
für die Universität Freiburg
Diplomarbeit
Christoph Litz
Gutachter: Prof. Dr. Gerhard Schneider
Institut für Informatik
Albert-Ludwigs-Universität Freiburg
Dezember 2004
1
Erklärung
Ich erkläre hiermit, die vorliegende Arbeit selbstständig, ohne Inanspruchnahme Dritter und nur mit den angegebenen Hilfsmitteln erstellt zu haben.
Freiburg, den 21. Dezember 2004
2
Dank
Bedanken will ich mich bei Herrn Prof. Dr. Schneider für die Durchsicht der
Arbeit und die freundlichen Hinweise. Herzlich danken möchte ich auch Herrn
Dr. Kraus und Herrn Bögenhold für die vielen wertvollen Ratschläge und die
gute Zusammenarbeit in einer angenehmen Atmosphäre. Mein besonderer
Dank gilt meinen Eltern und meiner Freundin Birgit für die kontinuierliche
Unterstützung während meines Studiums und bei dieser Arbeit.
Zusammenfassung
In der vorliegenden Arbeit wird erläutert, wie das Data Warehouse System
SuperX 2.1 an der Albert-Ludwigs-Universität Freiburg in Betrieb genommen
wird. Gemachte Erfahrungen werden dabei wiedergegeben und Empfehlungen für den Realbetrieb ausgesprochen. Des Weiteren behandelt die Arbeit
die Portierung des Systems in eine mobile Umgebung. Eingegangen wird
hierbei auf die Planung bis hin zu der Implementation. Die Ausarbeitung
eines Konzeptes zur Integration von grafisch visualisierten Daten schließt die
Arbeit ab.
Inhaltsverzeichnis
1 Einleitung
1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Aufbau dieser Arbeit . . . . . . . . . . . . . . . . . . . . . . .
2 Das Data Warehouse SuperX
2.1 Data Warehouse Grundlagen . . . . . . . . . . . .
2.1.1 Definition . . . . . . . . . . . . . . . . . .
2.1.2 Architektur eines Data Warehouse Systems
2.1.3 Phasen des Data Warehousing und OLAP
2.1.4 Anwendungsgebiete . . . . . . . . . . . . .
2.2 SuperX - ein Data Warehouse für Hochschulen . .
2.2.1 Beschreibung von SuperX . . . . . . . . .
2.2.2 Aufbau von SuperX . . . . . . . . . . . . .
2.2.3 Architektur von SuperX . . . . . . . . . .
2.3 Andere Data Warehouse Systeme . . . . . . . . .
3 SuperX an der Universität Freiburg
3.1 Stand der Dinge . . . . . . . . . . . . . . .
3.1.1 Ziele und Ideen . . . . . . . . . . .
3.1.2 Hochschulpolitischer Hintergrund .
3.2 Installation und Konfiguration . . . . . . .
3.2.1 Das Testsystem . . . . . . . . . . .
3.2.2 Installation der Software . . . . . .
3.2.3 Bedienung von SuperX . . . . . . .
3.2.4 Grafische Interfaces (Frontends) für
3.3 Erfahrungsbericht und Ergänzungen . . . .
3.3.1 PostgreSQL . . . . . . . . . . . . .
3.3.2 Installation . . . . . . . . . . . . .
3.3.3 Sicherung . . . . . . . . . . . . . .
3.3.4 Kommunikations-Struktur . . . . .
1
5
5
6
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
8
9
12
13
13
14
16
17
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
PostgreSQL
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
18
18
18
19
20
20
21
27
29
33
33
33
34
34
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
INHALTSVERZEICHNIS
2
4 Mobile SuperX
4.1 Welche Technologie soll verwendet werden?
4.2 PDAs: Palm und Pocket PC . . . . . . . .
4.2.1 Standards für drahtlose Netzewerke
4.2.2 Darstellung und Browsertechnik . .
4.3 Das XML-Frontend als Basis . . . . . . . .
4.4 Test- und Enwicklungsumgebung . . . . .
4.5 Implementation . . . . . . . . . . . . . . .
4.5.1 Anmeldung . . . . . . . . . . . . .
4.5.2 Untermenü . . . . . . . . . . . . .
4.5.3 Maske . . . . . . . . . . . . . . . .
4.5.4 Tabelle . . . . . . . . . . . . . . . .
4.5.5 Übersicht . . . . . . . . . . . . . .
4.6 Experimente: Browser und Pocket PC . . .
4.6.1 Internet Explorer Mobile . . . . . .
4.6.2 NetFront 3.1 . . . . . . . . . . . . .
4.7 Zusammenfassung . . . . . . . . . . . . . .
5 Diagramme für SuperX
5.1 SVG: Scalable Vector Graphics . . .
5.2 SuperX-Diagramme mit SVG . . . .
5.2.1 Eine statische SVG-Grafik . .
5.2.2 Eine dynamische SVG-Grafik
5.2.3 SVG auf dem Webserver . . .
5.2.4 Einbindung in SuperX . . . .
6 Abschlussbetrachtung und Ausblick
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
36
36
37
37
40
41
43
44
46
66
80
89
97
98
98
100
102
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
104
. 104
. 105
. 106
. 108
. 113
. 114
117
Abbildungsverzeichnis
.
.
.
.
.
.
.
.
.
.
.
.
10
11
12
15
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.8
3.9
3.10
3.11
Oberfläche von PostgreSQL . . . . . . . . . . . . . . . . .
Die Startseite von SuperX . . . . . . . . . . . . . . . . . .
Das Organigramm der Universität . . . . . . . . . . . . . .
Themenauswahl im SuperX-Applet . . . . . . . . . . . . .
Die Maske für die gewählte Abfrage . . . . . . . . . . . . .
Die Ergebnis-Tabelle der Abfrage . . . . . . . . . . . . . .
Das PostgreSQL Frontend Pg Access . . . . . . . . . . . .
Ein Ausschnitt der Tabelle Organigramm im phpPgAdmin
Das java-basierte Frontend SQL Workbench . . . . . . . .
Sieht Pg Access sehr ähnlich: pgAdmin III . . . . . . . . .
Kommunikations-Struktur für den SuperX-Betrieb . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
22
24
26
27
28
28
29
30
31
32
35
4.1
4.2
Ein Bluetooth Access Point verbindet PDAs mit dem LAN. .
Es gibt verschiedene Möglichkeiten einen PDA mit dem Internet zu verbinden. . . . . . . . . . . . . . . . . . . . . . . . .
Recht übersichtlich: n-tv.de mit NetFront ... . . . . . . . . .
... und etwas weiter nach rechts gescrollt . . . . . . . . . . .
Die Testumgebung für die Entwicklung von Mobile SuperX .
Das XML-Frontend von SuperX . . . . . . . . . . . . . . . .
Anmeldung für Mobile SuperX im Palm Web Browser . . . .
Das erste Menü von Mobile SuperX . . . . . . . . . . . . . .
Das Untermenü für die Kostenrechnung . . . . . . . . . . . .
Das Untermenü für die Administration . . . . . . . . . . . .
In der Maske kann die Anfrage spezifiziert werden. . . . . . .
Mobile Maske mit geöffnetem Pull-Down-Menue . . . . . . .
2.1 Architektur eines Data Warehouse . . .
2.2 Studierendenstatistik im OLAP-Würfel
2.3 OLAP: Slice and Dice . . . . . . . . .
2.4 Der Aufbau von SuperX . . . . . . . .
4.3
4.4
4.5
4.6
4.7
4.8
4.9
4.10
4.11
4.12
3
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. 39
.
.
.
.
.
.
.
.
.
.
.
40
42
42
44
45
47
66
80
80
90
90
ABBILDUNGSVERZEICHNIS
4
4.13 Kleine Tabellen werden von Mobile SuperX übersichtlich dargestellt. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.14 Mit Hilfe der Buttons kann man zur Auswahl zurückspringen.
4.15 Man hat die Auswahl welche Spalte, ein- bzw. ausgeblendet
werden soll. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.16 Dieselbe Tabelle, nachdem Spalte 2 und 4 ausgeblendet worden sind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.17 Der Ablauf von Mobile SuperX . . . . . . . . . . . . . . . . .
4.18 Mobile SuperX auf dem Internet Explorer Mobile . . . . . . .
4.19 Das Menü im Internet Explorer Mobile . . . . . . . . . . . . .
4.20 Mobile SuperX Untermenü im PPC IE . . . . . . . . . . . . .
4.21 Ein weiteres Untermenü im PPC IE . . . . . . . . . . . . . . .
4.22 Mobile SuperX Maske im PPC IE . . . . . . . . . . . . . . . .
4.23 Eine weitere Maske: Absolventen . . . . . . . . . . . . . . . .
4.24 Eine kleine Tabelle im Internet Explorer Mobile ... . . . . . . .
4.25 ... und eine sehr große Tabelle. . . . . . . . . . . . . . . . . . .
4.26 Die Mobile SuperX Anmeldung auf NetFront 3.1 . . . . . . . .
4.27 Das Menü auf NetFront 3.1 . . . . . . . . . . . . . . . . . . .
4.28 Das Untermenü auf NetFront 3.1 . . . . . . . . . . . . . . . .
4.29 Die Maske “Studierende“ . . . . . . . . . . . . . . . . . . . . .
4.30 Die Tabelle “Absoventen“ auf NetFront 3.1 . . . . . . . . . . .
4.31 Die Tabelle “Studierende“ im Vollbildmodus . . . . . . . . . .
96
97
98
98
99
99
99
99
100
100
101
101
101
101
102
102
5.1
5.2
5.3
5.4
108
115
115
116
absolventen balken.svg in Viewer Squiggle . . . . . . .
SVG-Diagramm der Absolventen in Mobile SuperX . .
SVG-Diagramm Anzahl Studierende in Mobile SuperX
SVG-Diagramm der Absolventen in Mobile SuperX . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
95
95
96
Kapitel 1
Einleitung
Bei dieser Diplomarbeit handelt es sich um eine sehr praxisnahe Arbeit, in
der das Data Warehouse SuperX an der Universität Freiburg eingesetzt und
angepasst werden sollte. Sie entstand in Zusammenarbeit mit der Verwaltung
(Dezernat 1) der Universität. Ziel der Arbeit war zunächst die produktionsreife Installation des Systems. In einem weiteren Schritt folgte die Entwicklung und Realisierung von mobilen Szenarien zum flexiblen Zugriff auf die
Informationen.
1.1
Motivation
Um für Thema zu motivieren, möchte ich zu Beginn dieser Arbeit ein Szenario skizzieren, in dem eine Hochschule ohne Data Warehouse auskommen
muss. Hochschulrankings versuchen einen Vergleich zwischen verschiedenen
Hochschulen zu erstellen, um angehenden Studenten die Auswahl der geeigneten Universität zu erleichtern. In diesem Zusammenhang könnten zum
Beispiel folgende Fragen auftauchen:
• Wie viele Studierende gibt es pro Professur?
• Wie viele Lehrveranstaltungen werden angeboten?
• Wie hoch ist die Erfolgsquote?
• Wie lang ist die Durchschnittsstudiendauer?
• Wie viele Forschungsprojekte, mit welchem Drittmittelvolumen, werden durchgeführt?
5
KAPITEL 1. EINLEITUNG
6
Um diese Fragen zu klären, müsste man die einzelnen Sachgebiete (Studierende, Personal, Forschung, ...) befragen, auf amtliche Veröffentlichungen zurückgreifen oder neue SQL-Anfragen auf verschiedenen Datenbanken
durchführen[1]. Das Problem liegt darin, dass vorhandene Daten teilweise
veraltet sind, die Schlüssel unvergleichbar sind und das Ergebnis teils auf
Papier, teils digital vorliegt. Dieser Zustand macht es sehr schwierig, die
Zahlen der Öffentlichkeit gegenüber zu rechtfertigen. Ein gut geplantes Data
Warehouse hat das Potential, diese Missstände zu beseitigen! Selbstverständlich hat ein Data Warehouse noch wesentlich mehr Anwendungsgebiete, als
ein Hochschulranking mit Zahlen zu versorgen.
1.2
Aufbau dieser Arbeit
Nach dieser Einleitung werden in Kapitel 2 die Themen “Data Warehouse“
und “SuperX“ zunächst theoretisch beleuchtet. Das Kapitel 3 beginnt wiederum mit einigen theoretischen Vorüberlegungen, bevor es im praktischen Teil
des Kapitels zur Beschreibung des Installations- und Konfigurationsvorganges von SuperX kommt. In Kapitel 4 wird vorgestellt, wie SuperX angepasst
wird, um auch für mobile Endgeräte, insbesondere PDAs, verfügbar zu sein.
Einen Ansatz, wie man SuperX um die Darstellung von Diagrammen erweitert, beschreibt Kapitel 5. Das Kapitel 6 beinhaltet die Abschlussbetrachtung
und den Ausblick.
Kapitel 2
Das Data Warehouse SuperX
A data warehouse is a copy of transaction data specifically structured for querying and reporting - Ralph Kimball
In diesem Kapitel möchte ich einige wichtige Begriffe und Abläufe aus den
Bereichen Data Warehouse und SuperX erläutern. Zunächst gehe ich auf die
Data Warehouse-Theorie ein, bevor ich die Funktionsweise und die Möglichkeiten von SuperX selbst beschreiben werde.
2.1
Data Warehouse Grundlagen
In der Betriebswirtschaftslehre spricht man normalerweise von den drei Produktionsfaktoren Boden, Arbeit und Kapital. Häufig wird in letzten Jahren
noch die Information als vierte Säule hinzugenommen[2]. Ein Informationssystem, hier im speziellen ein Data Warehouse, soll die gewünschten Informationen dem Anwender, zum Beispiel dem Manager oder dem Controller,
liefern und veranschaulichen. Die Data-Warehouse-Idee an sich ist nicht neu,
bereits in den sechziger Jahren gab es erste Ansätze für ein “ManagementInformationssystem“. Allerdings scheiterten diese Ideen an den nicht vorhandenen Voraussetzungen, wie zum Beispiel ausreichend kostengünstigem und
schnellem Datenspeicher.
2.1.1
Definition
Im allgemeinen sagt man kurz “Data Warehouse“ und meint damit eigentlich ein “Data Warehouse System“. Korrekterweise ist ein Data Warehouse
“nur“ eine physische Datenbank, welches ohne ein Data Warehouse System
nutzlos wäre. Dieser Sachverhalt ist vergleichbar mit dem Zusammenhang
7
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
8
von “Datenbank“ und “Datenbanksystem“. Der Begriff “Data Warehouse“
wird sehr vielseitig verwendet und es existiert deshalb keine allgemeingültige
Definition. Dies liegt unter anderem daran, dass zwei grundsätzliche Sichten
auf ein Data Warehouse möglich sind. Zum einen von der technischen Seite, die die Grundlagen der Datenbanksysteme enthält, zum anderen von der
Anwendungsseite, die die betriebswirtschaftlichen Anforderungen enthält.
Kennzeichen eines Informationssystemes ist, dass Daten erfasst und verwaltet werden[3]. Dabei unterscheidet man zwei verschiedene Integrationsmöglichkeiten[2]. Bei der Frontend-Integration werden Daten aus verschiedenen Systmen nur durch eine gemeinsame Oberfläche integriert, ein Beispiel
ist das Web-Portal Yahoo mit seinen Verweisen (Hyperlinks) auf Webseiten
anderer Betreiber. Das Data Warehouse wird der Backend-Integration zugeordnet, die Daten werden hier physisch in einer eigenständigen Datenbank
integriert. Ein wichtiger Unterschied im Vergleich zu einer klassischen Datenbank ist, dass in einem Data Warehouse die Daten durch den Anwender
nicht modifiziert werden können, er hat somit nur ein Lese-Recht. Eine Ausnahme bildet eventuell der Administrator des Data Warehouse. Hingegen
können dem Benutzer eines Datenbanksystems neben dem SELECT-Recht
auch UPDATE- und INSERT-Rechte zustehen. Im Vordergrund steht also
ganz klar die Analyse und nicht die Bearbeitung der Daten.
Deshalb definieren Bauer und Günzel[2] ein Data Warehouse folgendermassen:
“Ein Data Warehouse ist eine physische Datenbank, die eine integrierte Sicht auf beliebige Daten zu Analysezwecken ermöglicht.“
Eine Definitions-Variante von Ralph Kimball wurde bereits zu Beginn
dieses Kapitels beschrieben[4]. Beide sind auch auf das Data Warehouse SuperX passende Definitionen. Vergleichen kann man es mit einem Handelslager, in dem es viele vollkommen verschiedene Produkte (im Data Warehouse:
Daten) gibt, die innerhalb eines einzigen Raumes gelagert werden. Das Wort
“Warehouse“ übersetzt man somit wohl am treffensten mit “Lagerhaus“ oder
“Speicher“ und nicht, wie vielleicht zu erwarten, mit “Warenhaus“.
2.1.2
Architektur eines Data Warehouse Systems
Ein Data Warehouse System besteht aus verschiedenen Komponenten, wobei
die zentrale Komponente der Data-Warehouse-Manager ist. Er ist für die
Initiierung, Steuerung und Überwachung der einzelnen Prozesse zuständig[2].
Der Datenfluss beginnt bei der Datenquelle. Sie besteht aus mehreren
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
9
realen Datenquellen, dies könnten zum Beispiel eine Oracle Datenbank mit
Personaldaten und eine Informix Datenbank mit Verkaufszahlen sein. Bei der
Auswahl der Datenquelle für das Data Warehouse System sind der Zweck,
die Qualität und die Verfügbarkeit und eventuell auch der Preis der Daten
entscheidend.
Aus der Datenquelle werden die Daten in den Arbeitsbereich extrahiert
(Extraktionsphase), in ihm werden die Daten vorübergehend zwischengespeichert. Der Vorteil liegt darin, dass hier direkt notwendige Transformationen
(Transformationsphase) durchgeführt werden können, ohne dass die Datenquelle oder das Data Warehouse selbst beeinflusst, beziehungsweise manipuliert werden. Im nächsten Schritt werden die Daten in die Basisdatenbank
geladen und von dort in die verschiedenen Data Warehouses, in vielen Fällen
auch nur in ein einziges, verteilt (Ladephase). In der Praxis wird häufig auf
die Basisdatenbank verzichtet, da Aufbau und Pflege sehr aufwendig sind.
Im Data Warehouse selbst liegen somit nur noch die für die Analysephase aufgearbeiteten und benötigten Daten. Realisiert werden kann das Data
Warehouse zum Beispiel durch ein relationales Datenbanksystem wie PostgreSQL oder Informix.
Die Analyse beinhaltet Anfragen, Darstellung und die Anwendung von
Analysefunktionen (z.B. arithmetische Operationen). Als Darstellungsform
eignen sich Tabellen und Grafiken sehr gut, aber auch eine multimediale
Darstellung ist denkbar. Letztendlich sollte der Anwender die gesuchte Information in einer übersichtlichen Form präsentiert bekommen.
Eine weitere Komponente ist der Monitor, er dient zur automatischen
Entdeckung von Datenmanipulationen (Änderungen) in der Datenquelle. Nachdem der Monitor die Manipulation erkannt hat, kann er den Data-WarehouseManager dazu veranlassen, diese auch im Data Warehouse zu übernehmen.
Abbildung 2.1 soll den vollständigen Data-Warehouse-Prozess nochmals veranschaulichen.
2.1.3
Phasen des Data Warehousing und OLAP
Mit dem Monitoring beginnt auch der Data-Warehouse-Prozess, dessen einzelne Phasen hier kurz aufgelistet werden:
1. Monitoring
2. Extraktionsphase
3. Transformationsphase
4. Ladephase
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
10
Abbildung 2.1: Architektur eines Data Warehouse
5. Analysephase
Die Punkte 1. bis 4. wurden bereits erläutert, beziehungsweise erklären sich
von selbst. Auf Punkt 5 möchte ich allerdings etwas intensiver eingehen.
Man kann die Analyse in drei anhand der Flexibilität der Benutzeroberfläche
klassifizierte Ansätze einteilen: Data Access, Online Analytical Processing
und Data Mining.
Data Access
Mit dem Ansatz des Data Access leitet man zweckorientierte Informationen
aus Daten, die zum Beispiel in einer relationalen Datenbank abgelegt sind,
ab[2]. Als Datenmanipulationssprache dient hier vor allem SQL (Structured Query Language). Typische Fragestellungen im Data Access wären zum
Beispiel: “Wie viele Einheiten des Artikels Palm T5 wurden in der Filiale
Freiburg im 4. Quartal 2004 verkauft?“ oder “Wie viele Studierende der Informatik befinden sich im 6. Semester und haben das Vordiplom noch nicht
abgelegt?“
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
11
Abbildung 2.2: Studierendenstatistik im OLAP-Würfel
Online Analytical Processing (OLAP)
Online Analytical Processing erzeugt Anfragen, die einen dynamischen, flexiblen und interaktiven Zugriff auf die Daten erlauben[2]. Hierbei liegt ein
multidimensionales Datenmodell zugrunde, zur Darstellung und Visualisierung eignet sich ein Würfel sehr gut. Ein Würfel hat drei Dimensionen, die
jeweils zu einer ausgewählten Entität (Tabelle) gehören. Die Abbildung 2.2
zeigt einen solchen OLAP-Würfel am Beispiel einer Studierendenstatistik.
Die Dimensionen sind hier die Tabellen Fachbereich, Semester und Anzahl
Fachsemester. Durch Unterteilung der Dimensionen können weitere Dimensionselemente gebildet werden. Dies könnte für den Fachbereich Informatik
zum Beispiel eine Unterteilung in Medizinische Informatik, Medieninformatik und Allgemeine Informatik sein. Eine höhere Dimension für die Anzahl
der Fachsemester wäre vielleicht 1.-4. FS, 5.-8. FS, 9.-13. FS und >14. FS.
Die Dimensionselemente kann man sich als Baum vorstellen, in dem jedes
Element einen Knoten darstellt. Den Pfad von der Wurzel bis zum Blatt
nennt man Konsolidierungspfad. In dem Beispiel studieren im Sommersemester 2003 also 21 Studenten Informatik im 2. Fachsemester.
Für die Datenanlayse enthält OLAP ebenfalls spezifische Operatoren, mit
deren Hilfe innerhalb der multidimensionalen Datenstruktur navigiert werden
kann:
• Rotation (Pivotierung): Der Würfel wird durch Vertauschen der Dimensionen um seine Achsen gedreht.
• Roll-up, Drill-down und Drill-across: Beim Drill-down werden die Daten entlang des Konsilidierungspfades immer stärker aggregiert (zum
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
12
Abbildung 2.3: OLAP: Slice and Dice
Beispiel vom Dimensionselement Informatik zu den unterschiedlichen
Informatikbereichen). Roll-up ist die dazu komplementäre Operation.
Mit Hilfe des Drill-across-Operators wechselt man von einem zu einem
anderen Würfel.
• Slice and Dice: Beide Operatoren erzeugen individuelle Sichten auf die
Daten. Beim Slice werden einzelnen Scheiben aus dem Würfel geschnitten. Teilwürfel können mit Dice erzeugt werden (siehe Abbildung 2.3).
Für SuperX existiert ebenfalls eine OLAP-Realisierung.
Data Mining
Mit dem Analyseansatz des Data Mining werden Daten auf Regelmässigkeiten, Muster, Auffälligkeiten sowie auf jegliche Art von Beziehungen und
gegenseitiger Beeinflussungen untersucht[3]. Zu den angewandten Verfahren
gehört zum Beispiel das Clusterverfahren, bei dem Objekte aufgrund von
Ähnlichkeiten zu Gruppen zusammengefügt werden. Da Data Mining für SuperX im Moment keine wichtige Rolle spielt, möchte ich an dieser Stelle auf
die entsprechende Literatur verweisen und diesen Abschnitt beenden.
2.1.4
Anwendungsgebiete
Es existiert eine Fülle von Anwendungsgebieten für Data Warehouses, wobei
im Vordergrund immer die Analysierbarkeit der Daten steht:
• Betriebswirtschaftliche Anwendungsgebiete: Jeder Bereich eines Unternehmens ist heutzutage auf eine Fülle von Informationen angewiesen, die Marktingabteilung zum Beispiel auf Kundenstatistiken und
-verhalten.
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
13
• Wissenschaftliche Anwendungsgebiete: Das Projekt Earth Observing
System1 beispielsweise sammelt weltweit Daten zur Klima- und Umweltforschung von verschiedenen Bodenstationen und Satelliten. Bei
solch gigantischen Datenmengen (täglich ca. 1 TeraByte!) macht die gezielte Aufarbeitung in einem Data Warehouse für die Analyse natürlich
sehr viel Sinn.
• Technische Anwendungsgebiete: Zum Beispiel kann der Verlauf von
Messwerten aus Wasseranalysen beobachtet werden. An dieser Stelle macht es sich positiv bemerkbar, dass Daten im Data Warehouse
zeitabhängig sind.
Diese Beispiele sollen vorerst genügen, im nächsten Abschnitt wird mit SuperX ein Data Warehouse ausführlich erläutert.
2.2
SuperX - ein Data Warehouse für Hochschulen
SuperX ist ein Data Warehouse für Hochschulen und wurde ursprünglich in
den neunziger Jahren an Universität Karlsruhe entwickelt. SuperX stand damals für: System zur Unterstützung von Planung und Entscheidung des Rektorats durch Information, Controlling und Simulation. Inzwischen wird das
System als Opensource-Produkt von der Firma Memtext2 weiterentwickelt.
2.2.1
Beschreibung von SuperX
SuperX soll einer Gruppe von Anwendern als universelles Hochschulinformationssystem dienen. Anwender können zum Beispiel Mitarbeiter des Rektorats, Dekane einer Fakultät, Professoren und andere Mitarbeiter der Universität sein. SuperX beinhaltet deshalb ein ausgearbeitetes Berechtigungskonzept, um alle Anwender mit den für sie nötigen Informationen zu versorgen, nicht aber mit denen, die sie nicht “sehen“ sollen. So ermöglicht
es die Nutzerverwaltung einzelnen Anwendern oder Gruppen Leserechte auf
bestimmte Themenbereiche (Sachgebiete) zu geben. Parallel dazu ist es ebenfalls möglich, Leserechte auf Institutionen (organisatorische Einheiten) und
deren Unterinstitutionen zu vergeben. Denkbares wäre zum Beispiel, dass
der Dekan der Fakultät für Angewandte Wissenschaft Zugriff auf die Haushaltsdaten des Instituts für Informatik hat, nicht aber auf die des Instituts
für Physik.
1
2
http://eospso.gsfc.nasa.gov sowie http://www.eoscenter.com
http://www.memtext.de
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
14
Es stellt sich natürlich die Frage, warum der Aufwand betrieben werden
soll, ein gewaltiges Data Warehouse aufzubauen, wenn die Daten sowieso
bereits in anderen Datenbanken vorhanden sind. Dies hat aber einige gravierende Vorteile, die ich an dieser Stelle auflisten möchte:
• Im Vergleich zu den operativen Systeme (Datenquellen), die oftmals
stark belastet sind, ergibt sich im Data Warehouse eine höhere Performance.
• Es können Anfragen auf die Kombination verschiedenster Datenquellen gestellt werden. Zum Beispiel eine Anfrage, die sich auf Daten aus
dem Controlling-Modul COB und dem Bau-Modul bezieht: “Wieviele Drittmittel erwirtschaftet ein Lehrstuhl pro Quadratmeter?“ Eine
Erläuterung der Module erfolgt im nächsten Abschnitt.
• Die Daten werden in SuperX zeitabhängig gespeichert, so lassen sich
auch Daten aus der Vergangenheit analysieren, Trends ablesen sowie
Prognosen erstellen.
• Durch die einheitliche Oberfläche für alle Informationen ergibt sich eine
deutlich einfachere Handhabung und weniger Schulungsaufwand für die
einzelnen Anwender.
• Es gibt nur eine Nutzer- und Rechteverwaltung für das System, mit der
Informationsinhalte aller Art abgedeckt werden. Ansonsten müssten für
jede Datenbank Benutzer-Rechte einzeln vergeben werden.
2.2.2
Aufbau von SuperX
Im Folgenden möchte ich den Aufbau von SuperX erläutern und mit dem
Modell aus Kapitel 2.1.2 vergleichen. Grundsätzlich kann man den Aufbau
des SuperX-Systems in drei Teile untergliedern[6]:
• Datenquellen
• Data Warehouse
• Frontends
Abbildung 2.4 zeigt den Ablauf des Data-Warehouse-Prozesses für SuperX
von der Datenquelle bis zum vom Anwender bevorzugten Frontend.
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
15
Abbildung 2.4: Der Aufbau von SuperX
Datenquellen
Als Datenquellen für SuperX dienen die Verwaltungssysteme der HochschulInformations-System GmbH3 , z.B. HIS-COB und HIS-SOS. Diese Systeme
basieren jeweils auf einer konventionellen relationalen Datenbank. SuperX
ist modular aufgebaut und kann deshalb nach und nach um die von der
Universität gewünschten Module erweitert werden. Das HIS-Portfolio umfaßt
der Zeit die folgenden operativen Systeme:
• Studentenverwaltung SOS
• Prüfungsverwaltung POS
• Zulassungsverwaltung ZUL
• Integrierte Finanz- und Sachmittelverwaltung FSV
• Gebäude- und Flächenmanagement BAU
• Kosten- und Leistungsrechnung COB
• Personal- und Stellenverwaltung SVA
• Lehrveranstaltungsmanagement: Lehre, Studium, Forschung LSF
Entsprechende SuperX-Module werden von Memtext einzeln zur Verfügung
gestellt. Dies soll aber nicht bedeuten, dass es nicht möglich ist, auch Datenquellen in SuperX zu übernehmen die nicht von HIS stammen.
3
http://www.his.de
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
16
Data Warehouse
Durch Übernahme- und Transformations-Skripte werden die benötigten Daten in die relationale SuperX-Datenbank geladen. Dies entspricht der Extraktions- und Transformationsphase im Modell aus Kapitel 2.1.3. Im Einzelnen
werden also Daten aus einer Datenbank entladen und in eine Datei geschrieben, diese Datei wird auf den SuperX-Rechner übertragen und dort werden
die entsprechenden Tabellen mit den Daten aus der Datei gefüttert. Alle Daten, die SuperX benötigt, liegen also in einer “grossen“ SuperX-Datenbank.
Neben dieser gibt es noch eine weitere Datenbank, die multidimensionale
Joolap-Datenbank (siehe unten).
Frontends
Mit Hilfe verschiedener Frontends können nun die Analysen und Auswertungen vorgenommen werden. Folgende Frontends sind integriert:
• SuperX-Applet: Es handelt sich hierbei um ein Java-Applet, welches
über den Browser aufgerufen werden kann. Benötigt wird nur das J2SE
Java Runtime Environment (JRE) von SUN. Es ist also keine explizite
Installation von SuperX auf einem Client nötig!
• XML-Frontend: Ebenfalls browserbasiertes Frontend, aber auf Basis
von XML und XSL-Stylesheets. Eine ausführliche Beschreibung folgt
im Zusammenhang mit dem Frontend “Mobile SuperX“ (siehe unten).
• JOOLAP4 : Mit Joolap können Daten auf OLAP-Basis analysiert werden. Dabei werden flexible Auswertungen und Ergebnistabellen per
Mausklick zusammengestellt.
Teilaufgabe dieser Diplomarbeit war die Ausarbeitung und Umsetzung eines Konzeptes, um SuperX auch mit mobilen Endgeräten, insbesondere mit
PDAs, nutzen zu können. Dabei enstand ein neues Frontend:
• Mobile SuperX: Es basiert auf dem XML-Frontend. Eine ausführliche
Beschreibung und die Implementation folgt in Kapitel 4.
2.2.3
Architektur von SuperX
Um SuperX einsetzen zu können, benötigt man folgende Komponenten[6]:
4
http://joolap.memtext.de
KAPITEL 2. DAS DATA WAREHOUSE SUPERX
17
• Einen Datenbankserver, der das eigentliche Data Warehouse mit Benutzer- und Gruppenverwaltung, Schlüsseln, Administrationswerkzeugen und Modulen beinhaltet.
• Einen Web- und Application-Server, der die Daten an die Clients beziehungsweise an die Frontends liefert.
• Die SuperX-Clients (Browser), auf denen das jeweilige Frontend läuft.
Wie die Konfiguration und Installation im Einzelnen verläuft, erläutere ich
in Kapitel 3.
2.3
Andere Data Warehouse Systeme
Selbstverständlich ist SuperX nicht das einzige Data Warehouse für Hochschulen. An bayrischen Hochschulen wird zum Beispiel das Computerbasiertes Entscheidungsunterstützungssystem 5 (CEUS) eingesetzt[7]. Die UniWebDatenbank: Stift 6 dient der Universität Osnabrück als Management-Informations-System (MIS) und ist wie SuperX eine browserbasierte Anwendung.
Die Branchenriesen im Bereich Datenbanken bieten ebenfalls alle eigene
Data Warehouse Systeme an. Oracle nennt sich selbst Marktführer in diesem Bereich. Beispielsweise beruht der Erfolg von Amazon.com - zumindest
teilweise - auf dem Einsatz von Oracle Datawarehousing. Weitere Lösungen
werden unter anderem auch von SAS und SAP angeboten.
5
6
http://ceus.uni-bamberg.de/
http://sansibar.oec.uni-osnabrueck.de/pls/mss/fuwd?SelDB=UWDSTIFT
Kapitel 3
SuperX an der Universität
Freiburg
Nach der eher theoretischen Sicht auf SuperX folgt nun in diesem Kapitel
der praktische Teil der Beschreibung. Diese beeinhaltet den Stand vor Beginn
dieser Arbeit, die Betrachtung des hochschulpolitischen Hintergrundes sowie
die Installation und Testphase von SuperX.
3.1
Stand der Dinge
SuperX war in Freiburg bereits vor dieser Arbeit im Einsatz. Dabei handelt es sich allerdings um die “alte“ Karlsruher Variante. Die neue Version
(SuperX 2.1) bringt neben einem erweitertem Funktionsumfang insbesondere
die Unterstützung von PostgreSQL mit sich, was sich vor allem auf die Lizenzkosten im Vergleich zu Informix sehr positiv auswirkt. Ein Vergleich der
beiden Datenbanksysteme folgt weiter unten. Genutzt wurde SuperX bisher
nur von wenigen Anwendern aus der Verwaltung der Universität. Mitarbeiter
aus anderen Einrichtungen haben bisher keinen Zugang zu dem System.
3.1.1
Ziele und Ideen
Mit der Installation der neuen SuperX-Version verfolgt man einige Ziele,
insbesondere für das Controlling, die hier aufgelistet werden sollen.
• Die neue Version hat neue Features (z.B. das XML-Frontend), die man
natürlich verwenden möchte.
• Umstellung von Informix auf das frei erhältliche Datenbank-System
PostgreSQL.
18
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
19
• SuperX soll umfassendes Hochschulinformationssystem für Freiburg werden.
• Anwender aus den verschiedensten Bereichen der Universität sollen Zugriff auf die Daten bekommen, ein gut durchdachtes Berechtigungskonzept soll dies ermöglichen. Dabei muss bedacht werden, dass es zu
Problemen mit alternativen Hierarchien kommen kann. Nimmt man
zum Beispiel Auswertungen auf der Studiengangebene Informatik, so
ist nicht nur das Institut für Informatik, sondern auch das Mathematische Institut an der Lehre beteiligt.
• Zukünftig sollte die Authentifizierung über den bereits vorhandenen
LDAP-Verzeichnisdienst abgewickelt werden.
• Möglichst viele der HIS-Grundsysteme sollen als Module in SuperX
integriert werden (Anmerkung: an der Entwicklung des SOS-Moduls
ist die Universität Freiburg beteiligt).
• Nicht zuletzt ist geplant, SuperX zur Erstellung der Berichte für das
Ministerium für Wissenschaft, Forschung und Kunst Baden-Württemberg1 zu verwenden (siehe dazu Kapitel 3.1.2).
Einige der oben genannten Ziele sind momentan noch nicht umsetzbar, es
wird aber versucht in verschiedenen Arbeitsgruppen Lösungen zu finden.
3.1.2
Hochschulpolitischer Hintergrund
Durch Veränderungen innerhalb der Mittelverteilung, welche in Zukunft leistungsorientierter sein soll, stehen die Hochschulen immer mehr in Konkurrenz zueinander. Aber auch der Wettbewerb um neue Studenten gewinnt
immer mehr an Bedeutung. Hochschulrankings, wie zum Beispiel von Stern2 ,
Spiegel3 und Focus, tun dazu ihr Übriges. Um international konkurrenzfähig
zu bleiben, entstanden Diskussionen über zukünftige Elite-Universitäten, dadurch verschärft sich die Konkurrenzsitutation zusätzlich. Ziel der Hochschulen ist es also, ihre Leistung zu verbessern, um attraktiv für Studenten und
Wissenschaftler zu sein. Zunächst muss man sich aber klar machen, welche Aufgaben (betriebswirtschaftlich: Ziele) eine Hochschule hat. Sie werden
1
http://www.mwk-bw.de
http://www.dashochschulranking.de/
3
http://www.spiegel.de/unispiegel/studium/0,1518,329133,00.html
2
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
20
durch das Hochschulrahmengesetz festgelegt, wobei “die Pflege und Entwicklung der Wissenschaften und der Künste durch Forschung, Lehre, Studium
und Weiterbildung“4 im Vordergrund stehen.
Nun stellt sich natürlich die Frage, wie bewertet werden soll, wie gut
eine Universität die vom Land übertragen Aufgabe erfüllt hat. Ein fundiertes
und professionelles Informationssystem, welches eventuell auch einheitlich im
Land verwendet wird, wäre dafür ein gutes Werkzeug. Bestrebungen in diese
Richtung laufen gerade im Zusammenhang mit SuperX. Wie oben bereits
erwähnt kann SuperX auch bei der Erstellung der Berichte, nach denen die
Universitäten verglichen werden können, behilflich sein.
In den meisten Wirtschaftsunternehmen ist Information heute ein wichtiger Bestandteil (“vierte Säule“) des betrieblichen Geschäftsprozesses[3]. Für
Hochschulen verhält es sich, wie oben beschrieben, sehr ähnlich und SuperX
kann in diesem Zusammenhang für die Universität Freiburg in Zukunft eine
grosse Rolle spielen.
3.2
Installation und Konfiguration
Bevor die neue Version offiziell zum Einsatz kommt, muss sie natürlich ausführlich getestet werden. Insbesondere die Installation ist nicht trivial und verlangt doch einigen Aufwand. Sie wurde in Zusammenarbeit mit Herrn Klaus
Bögenhold aus der Verwaltung der Universität durchgeführt.
3.2.1
Das Testsystem
Als Testsystem diente uns ein Fujitsu-Siemens Scenic W6005 PC mit folgender Konfiguration:
• Intel Pentium 4 2,6 GHz
• 1024 MB Hauptspeicher
• Chipsatz Intel i865G
Weitere Merkmale des Gerätes sind unter der angebenen Adresse zu finden.
Alles in allem ein System, welches im Bezug auf die reine Rechen-Power einem
kleinem “echten“ Serversystem wenig nachsteht. Einzig die Zuverlässigkeit,
zum Beispiel durch ein Raid-System, würde sich dadurch noch entscheidend
verbessern, was für die Testphase aber nicht unbedingt erforderlich ist.
4
Vgl. §2 Absatz 1 Hochschulrahmengesetz
http://www.fujitsu-siemens.de/products/personal computer/scenic w.html
(12.10.2004)
5
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
21
Als Betriebssystem diente Suse Linux Professional6 . Allerdings gab es
mit der Version 9.0 erhebliche Performance-Probleme, die vermutlich mit
den ACPI-Treibern (Advanced Configuration & Power Interface7 ) zusammenhängen. Dies ist umso erstaunlicher, wenn man bedenkt, dass der FujitsuSiemens W600 auf der Suse-Homepage für die Version 9.0 als zertifizierte
Hardware aufgelistet wird. Mit Erscheinen der Version 9.1 und der damit
verbundenen Neuinstallation hat sich das Problem dann allerdings erledigt.
Der Rechner wurde während der Testphase an das Verwaltungsnetzwerk
der Universität angeschlossen. Es handelt sich dabei um ein 100Mbit-Ethernet.
Die IP-Adresse wurde dynamisch per DHCP (Dynamic Host Configuration
Protocol) vergeben, nach der Testphase würde man selbstverständlich eine
feste IP-Adresse verwenden, zum Testen genügt uns aber eine dynamische.
3.2.2
Installation der Software
Nach der problemlosen Installation des Betriebssystems folgt die von SuperX.
Zunächst müssen einige Vorarbeiten durchgeführt werden, Folgendes wird
benötigt:
• Pakete zum Kompilieren von Programmen (C/C++ Compiler, make,
usw.), bei Suse Linux gibt es die Paketsammlung “C/C++ Compiler
und Werkzeuge“, die bereits alles enthält,
• Das SUN Java Software Development Kit,
• Einen Webserver, hier empfiehlt sich der HTTP-Server der Apache Software Group8 . Version 1.3 genügt unseren Ansprüchen hier eigentlich
vollkommen, Apache 2.0 funktioniert aber natürlich auch.
Oben genannte Software bildet das Fundament, auf dem das SuperX-System
nun aufgebaut werden kann. Man verwendet:
• PostgreSQL als Datenbank,
• das SuperX-Kernmodul, welches auch den Apache Jakarta Tomcat als
Servlet Container enthält,
• die bereitgestellten Module auf Basis der operativen HIS-Systeme.
6
http://www.suse.de/de/private/products/suse linux/prof/ (12.10.2004)
http://www.acpi.info
8
http://httpd.apache.org
7
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
22
Abbildung 3.1: Oberfläche von PostgreSQL
Die PostgreSQL-Datenbank
PostgreSQL9 ist ein open-source Datenbank-Management-System, welches
sich immer grösser werdender Beliebtheit erfreut. Insbesondere die Tatsache,
dass PostgreSQL unter der BSD-Lizenz vertrieben wird, welche es erlaubt,
die Software frei zu benutzen und zu verteilen, hat dazu geführt.
Nach dem Download und dem Kompilieren des Quellcodes kann die Datenbank für SuperX konfiguriert werden. Dafür wird der Benutzer “postgres“
angelegt, er ist der Besitzer der Datenbank “superx“, die ebenfalls angelegt
wird.
Welche Geräte tatsächlich Zugriff auf die Datenbank bekommen sollen,
lässt sich über die Konfigurationsdatei ../pgsql/data/pg hba.conf regeln[9].
Hier können IP-Adressen beziehungsweise ganze IP-Bereiche eingetragen werden, denen der Zugriff erlaubt werden soll. Wichtig ist, dass man nicht vergisst, in der postgres.conf tcpip socket = yes zu setzen. Eine Beschreibung
von grafischen Interfaces (Frontends) für PostgreSQL folgt in Kapitel 3.2.4.
9
http://www.postgres.org
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
23
Das SuperX-Kernmodul
Das SuperX-Kernmodul enhält alle Grundfunktionen von SuperX, das heißt,
sobald man es installiert und konfiguriert hat, ist SuperX einsatzfähig. Weitere Module können dann zu einem späteren Zeitpunkt dazu installiert werden. Alle nun folgenden Schritte werden als Linux-Benutzer “superx“ durchgeführt. Zunächst werden die Dateien in das Verzeichnis /home/superx entpackt. Danach sind einige Anpassungen in den Konfigurationsdateien notwendig, auf welche ich hier aber nicht im Einzelnen eingehen möchte, da dies
alles sehr gut und ausführlich in der Dokumentation von SuperX beschrieben
ist[6]. An diese Beschreibung sollte man sich exakt halten, da die Erfahrung
aufgezeigt hat, dass es sonst sofort zu Fehlern und Problemen kommen kann.
Nun kann das Kernmodul mit Hilfe des Skriptes kernmodul erzeugen.x
erzeugt werden. Dafür muss PostgeSQL laufen, da an dieser Stelle auch die
SuperX-Datenbank initialisiert wird. Gleichzeitig wird auch der Apache Jakarta Tomcat 4 als Servlet Container installiert. Von nun an ist die SuperXStartseite im Browser unter der Adresse http://localhost:8080/superx erreichbar (siehe Abbildung 3.2), dementsprechend muss der Port 8080 in der
Verwaltungs-Firewall auch nicht freigegeben werden. Mit dem Starten des
Servlet Containers (Tomcat) werden die SuperX-Servlet-Dateien initialisiert.
Servlets laufen, im Gegensatz zu Applets, auf dem Server und müssen also
nicht erst auf den Client übertragen werden. Somit liegt die Last, wie zum
Beispiel auch bei PHP, auf Seiten des Servers, daher auch der Begriff “serverseitig“. Das SuperX-Servlet versorgt die Client-Frontends mit den benötigten
Daten.
Tomcat beinhaltet zwar einen eigenen Webserver, es empfiehlt sich aber
trotzdem, ihn mit dem Apache Webserver zu verbinden, da dieser wesentlich
performanter ist. Außerdem ist es so nicht mehr nötig, den Port 8080 an
die URL zu hängen (siehe Adressleiste Abbildung 3.2). Die Anfragen werden
somit vom Apache an den Tomcat weitergeleitet. Zur Durchführung gibt es
in SuperX ein bereits vorkompiliertes Modul mod jk.so, lediglich ein paar
Anpassungen in den Konfigurationdateien des Tomcat sowie in der httpd.conf
des Apachen sind noch erforderlich.
Im nächsten Schritt wird nun die Verbindung per SSL (Secure Sockets
Layer Protocol) eingerichtet. Für den SSL-Betrieb benötigt der ApacheWebserver das Modul mod ssl.so und zum Erzeugen des Zertifikates sowie
der Schlüssel das Openssl10 -Paket. Wie bereits gesagt, es wird ein Zertifikat
erzeugt, welches wir für den Testbetrieb einfach selbst signieren, später kann
dies problemlos um ein öffentliches Zertifikat erweitert werden. Die Position des öffentlichen und des privaten Schlüssels geben wir wiederum in der
10
http://www.openssl.org
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
Abbildung 3.2: Die Startseite von SuperX
24
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
25
httpd.conf unseres Webservers an. Die Clients können unseren SuperX-Server
jetzt nur noch über eine sichere Verbindung, durch den Aufruf folgender
Adresse erreichen: https://<server-ip>/superx.
Um sich ein manuelles Starten von PostgreSQL, Apache und Tomcat zu
ersparen, empfiehlt es sich, diese als Dienste einzurichten. Das ist auch für
den realen Betrieb später sinnvoll, da der Server bei Problemen neu gestartet
werden kann, ohne dass der SuperX-Administrator oder andere “eingeweihte“ Personen die Programme von Hand starten müssen. Einzig der Apache
verlangt auf Grund des SSL-Betriebs die Eingabe des CA-Passwortes.
Die Module
Ein grosser Vorteil der neuen Version von SuperX ist die Möglichkeit, Module
nach und nach zu installieren, je nach den Bedürfnissen der Hochschule. Leider war zum Zeitpunkt dieser Arbeit auf der Download-Seite von Memtext
unter PostgreSQL nur das COB-Modul für die Kosten- und Leistungsrechnung verfügbar. Deshalb ist es mir auch nicht möglich, an dieser Stelle auf
die Installation weitere Module einzugehen. In Freiburg ist geplant, SuperX
unter Verwendung von PostgreSQL weiter auszubauen und tatsächlich so
viele Bereiche wie möglich abzudecken, damit es als umfassendes HochschulInformations-System eingesetzt werden kann.
Das COB-Modul hat eine zentrale Funktion in SuperX, es enthält nämlich
die Tabelle Organigramm. Das Organigramm gibt den strukturellen Aufbau der Universität baumartig wieder. Das Wurzelelement ist die “Universität Freiburg“, untergeordnet ist zum Beispiel die Fakultät für Angewandte
Wissenschaft, dieser wiederum ist das Institut für Informatik untergeordnet,
welches dann Vater der einzelnen Lehrstühle ist (siehe Abbildung 3.3). Die
Installation des Moduls selbst verläuft recht einfach, es gibt dazu auch eine sehr gute Beschreibung auf der SuperX-Homepage. Nach dem Download
wird alles im SuperX-Verzeichnis entpackt und die notwendigen Anpassungen
der Konfigurations-Dateien durchgeführt. Zu finden ist alles im Verzeichnis
/home/superx/db/module/cob. Der entscheidende Schritt ist nun das Extrahieren der Daten aus der Original-COB-Datenbank (Datenquelle). Dafür
steht ein Entladescript bereit, welches gleichzeitig die notwendigen Transformationen durchführt. Das ist notwendig, da es sich bei der Datenquelle um
eine Informix-Datenbank und bei unserem Data Warehouse ja bekanntlich
um eine PostgreSQL-Datenbank handelt. Als Beispiel seien hier exemplarisch
die unterschiedlichen Datentypen für Datumsangaben genannt, bei Informix
gibt es den Typ “datetime“, bei Postgres aber nur “date“[9]. Die Rohdaten
werden nun in das Verzeichnis /home/superx/db/module/cob/rohdaten kopiert. Jetzt kann das COB-Modul mit dem Skript cob modul erzeugen.x
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
26
Abbildung 3.3: Das Organigramm wird im Admin-Tool angezeigt
installiert werden. Im Applet, beziehungsweise in jedem beliebigen Frontend, erscheint jetzt der neue Zweig Kostenrechnung mit seinen verschiedenen Abfragen. Noch sind die COB-Tabellen nicht mit Daten gefüllt, dies
wird aber jetzt mit dem Befehl cob update.x geschehen, mit dem Parameter --mit-organigramm auch die Tabelle Organigramm, diese wird natürlich
nicht häufig verändert.
Der ganze Update-Vorgang muss selbstverständlich nicht jedesmal von
Hand durchgeführt werden, sondern wird durch Cron-Jobs regelmässig automatisch abgewickelt. Je nachdem wie häufig sich die Daten ändern, kann
dies zum Beispiel jede Nacht, aber auch nur wöchentlich oder noch seltener
geschehen. Bei Bedarf sind manuelle Updates natürlich weiterhin möglich.
Bei den Updates werden auch Log-Dateien angelegt, welche die Betreuer des
jeweiligen Sachgebietes oder der SuperX-Administrator auswerten können.
SuperX ist nun fertig installiert und somit einsatzbereit! Sobald weitere Module verfügbar sind, werden diese auf dieselbe Art und Weise wie das
COB-Modul konfiguriert. Es liegt jetzt an den Hochschulen selbst, gewünschte Änderungen (z.B. der Masken) und Erweiterungen (siehe Beispiel in Kapitel 5) vorzunehmen.
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
27
Abbildung 3.4: Themenauswahl im SuperX-Applet
3.2.3
Bedienung von SuperX
Die Bedienung von SuperX möchte ich beispielhaft am Java-Applet erläutern.
Dieser Abschnitt soll dabei nicht zu sehr auf die Details eingehen, siehe dazu
das Benutzerhandbuch von SuperX[5], sondern dem Leser, der SuperX noch
nicht gesehen hat, einen Eindruck von dem System vermitteln. Dies dient vor
allem dem besseren Verständnis der folgenden Kapitel.
Nachdem das Applet geladen ist, muss sich der Anwender mit seinem Benutzernamen sowie Passwort authentifizieren. Das Applet wird durch Karteikartenreiter in drei Teile getrennt: Themenauswahl, Maske und Tabelle.
Unter Themenauswahl kann man zwischen Abfragen, die baumartig angeordnet sind, entscheiden, zum Beispiel Administration - Benutzer - Benutzer
von SuperX (siehe Abbildung 3.4). Über die Maske können nun weitere Einschränkungen per Pulldown-Menü und Checkbox für die Abfrage getätigt
werden. In unserem Beispiel werden keine Einschränkungen getroffen (siehe
Abbildung 3.5), es werden also alle Benutzer von SuperX gesucht. Das Ergebnis der Abfrage wird dann unter der Auswahl Tabelle angezeigt. Ausserdem
stehen eine Druckfunktion sowie eine Funktion zum Kopieren der Tabellen
in eine Tabellenkalkulation zur Verfügung (siehe Abbildung 3.6).
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
Abbildung 3.5: Die Maske für die gewählte Abfrage
Abbildung 3.6: Die Ergebnis-Tabelle der Abfrage
28
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
29
Abbildung 3.7: Das PostgreSQL Frontend Pg Access
3.2.4
Grafische Interfaces (Frontends) für PostgreSQL
Wenn man Abbildung 3.1 betrachtet, fällt auf, dass die Oberfläche von PostgreSQL sehr spartanisch gehalten ist, was sich leider negativ auf die Benutzbarkeit auswirkt. Man kommt also nicht um ein geeignetes grafisches
Interface herum. Glücklicherweise hat man dafür aber viele zur Auswahl. Da
in der Verwaltung der Universität PostgreSQL bisher nicht eingesetzt worden
ist, weitere Umstellungen sind geplant, bot es sich an, einige dieser Interfaces
zu testen.
Pg Access
Pg Access11 ist vollständig in Tcl/Tk (Tool Command Language / Toolkit) geschrieben und für verschiedene Plattformen (Linux, Windows, Mac)
frei verfügbar. Auf der Suse Linux 9 DVD ist es bereits enthalten und kann
leicht mit Yast installiert werden, für Windows steht eine direkt ausführbare Exe-Datei zum Download bereit. Die Verbindung mit der Datenbank
funktionierte auf beiden Systemen problemlos, ebenso der Zugang von einem
entfernten PC. Alle wichtigen und grundlegenden Funktionen, die man zur
Administration einer Datenbank benötigt, sind enthalten. So können zum
Beispiel Benutzer und Gruppen verwaltet sowie Tabellen und Views erstellt
und verändert werden. Außerdem kann man komfortabel SQL-Anfragen an
die Datenbank stellen. Abbildung 3.7 zeigt Pg Access
11
http://www.pgaccess.org
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
30
Abbildung 3.8: Ein Ausschnitt der Tabelle Organigramm im phpPgAdmin
phpPgAdmin
Im Gegensatz zu allen anderen getesteten Frontends ist phpPgAdmin12 ein
browserbasiertes. Eine Installation ist nicht nötig, die Dateien werden nach
dem Download einfach in einem Verzeichnis, zum Beispiel direkt in httdocs,
des Webservers entpackt. Vorausetzung ist allerdings, dass auf dem Webserver PHP läuft, dies ist heutzutage ohnehin ein Quasi-Standard. Der Aufruf
geschieht jetzt direkt im Browser über http://localhost/phppgadmin/index.php
(siehe Abbildung 3.8). Von einem entfernten Rechner muss localhost natürlich
durch die IP-Adresse des Webservers ersetzt werden. Die Funktionen ähneln
denen von Pg Access stark. Von Vorteil kann die Option sein, Daten in verschiedenen Formaten (Text, XML, XHTML, CSV, ...) speichern zu können.
Mir persönlich hat dieses Frontend am besten gefallen, deshalb habe ich es
auch für die Datenbankveränderungen in Kapitel 4 und 5 verwendet.
12
http://phppgadmin.sourceforge.net
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
31
Abbildung 3.9: Das java-basierte Frontend SQL Workbench
SQL Workbench
Bei SQL Workbench13 handelt sich ebenfalls um ein frei verfügbares Tool,
welches komplett in Java geschrieben ist. Es läuft also auf jedem java-fähigen
System. Abbildung 3.9 zeigt das Frontend auf einer Windows-Plattform. SQL
Workbench beschränkt sich nicht nur auf PostgreSQL, sondern erlaubt es
auch, andere Datenbank-Systeme per JDBC-Treiber zu verbinden. Mehrere
Datenbanken können mit SQL Workbench gleichzeitig geöffnet werden und
Daten können mit dem sogenannten “Data Pumper“ zwischen verschiedenen
Servern und Datenbanken hin und her kopiert werden. Leider erwies sich das
Tool sich bei grossen Tabellen als nicht sehr stabil und stürzte immer wieder
ab, zumindest auf Suse Linux. Deshalb würde ich im Moment noch vom
Einsatz abraten und eher auf ein stabileres Frontend zurückgreifen. Trotzdem
lohnt es sich die Entwicklung von SQL Workbench im Auge zu behalten und
neuere Versionen nochmals auszuprobieren.
13
http://www.kellerer.org/workbench
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
32
Abbildung 3.10: Sieht Pg Access sehr ähnlich: pgAdmin III
pgAdmin III
Bei pgAdmin III14 handelt es sich um ein Frontend, bei dem über 100 Personen aus aller Welt an der Entwicklung beteiligt sind. Aussehen und Funktionen erinneren stark an das oben beschriebene Pg Access (siehe Abbildung
3.10).
Kommerzielle grafische Interfaces
Neben den oben genannten freien Frontends gibt es auch kommerzielle Software zu diesem Thema. Einige möchte ich kurz nennen:
• PgManager von EMS (Windows, Linux)
• EduPhant von Aliacta (Windows, Mac)
• DBone von Fox Software (Windows)
• PG Explorer (Windows)
14
http://www.pgadmin.org
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
3.3
33
Erfahrungsbericht und Ergänzungen
In diesem Abschnitt möchte ich die Erfahrungen, die bei der Installation von
SuperX gemacht worden sind, sowie einge persönliche Meinungen zu dem
Thema wiedergeben.
3.3.1
PostgreSQL
Einen sehr gründlichen Vergleich zwischen den beiden Datenbank-Systemen
PostgreSQL und Informix findet man auf der Webseite http://postgres.superxprojekt.de. Dazu möchte ich lediglich ein Paar Punkte ergänzen. Inzwischen
gibt es die sehr gute, offizielle PostgreSQL-Dokumentation auch auf Deutsch,
sie ist als Buch im mitp-Verlag erschienen[9]. Erfreulich ist, dass das gesamte
Buch auch in HTML- beziehungsweise in PDF-Form frei zum Download zur
Verfügung steht. Unter http://www.postgres-forum.de findet man seit 2003
nun auch ein sehr nützliches deutschsprachiges Forum. In Version 7.4 werden GROUP-BY-Anfragen durch Hash-Aggregierung im Hauptspeicher beschleunigt, was sich vor allem für Data Warehousing und OLAP-Anwendung
positiv bemerkbar macht[10]. Des Weiteren wurde erstmalig eine Optimierung für AMDs 64-bit Opteron-Prozessor vorgenommen, was man beim Einsatz des Servers durchaus bedenken sollte. PostgreSQL 8 wird von Grund
auf auch auf Windows-Systemen laufen, bisher musste man mit Cygwin
(Unix-Umgebung für Windows) arbeiten. Somit wäre es theoretisch denkbar, die SuperX-Datenbank auf einem Windows-System laufen zu lassen,
ob dies wirklich Sinn macht, sei dahingestellt. Die Version 8.0 befand sich
während des Schreibens dieser Arbeit allerdings noch im Beta-Stadium. Das
Laden und Entladen von Tabellen ist durch die grafischen Frontends wesentlich komfortabler geworden.
Im Vergleich zu dem anderen beliebten open-source Datenbanksystem
MySQL15 ist PostgreSQL bei komplexen Anfragen schneller, MySQL hingegen bei einfachen SELECT-Anfragen[15]. Somit ist PostgreSQL für SuperX
eher geeignet. Die einzelnen Funktionen sind schwer miteinander zu vergleichen, da beide Systemen rasant weiterentwickelt werden.
3.3.2
Installation
Es empfiehlt sich unbedingt der Installationsanleitung auf der SuperX-Webseite
ganz genau zu folgen. Ansonsten kann es, wie bereits weiter oben erwähnt, zu
bösen Überraschungen kommen. Aufpassen muss man vor allem bei den hochschulspezifischen Einstellungen sowie bei der Konfiguration des Tomcats. Bei
15
http://www.mysql.org
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
34
der Einrichtung der Dienste muss man darauf achten, dass die Startreihenfolge (PostgreSQL vor SuperX) beibehalten wird.
3.3.3
Sicherung
Während der Testphase kann natürlich auch einmal etwas schief gehen, daher bietet es sich an, das komplette System an bestimmten Fixpunkten zu
sichern. Dafür wird ein Image der gesamten Partition erstellt, welches bei
Bedarf dann wieder zurückgesichert werden kann. Für Windows gibt es dazu
zum Beispiel Norton Ghost, dies funktioniert aber nicht mit dem auf dem
Testserver verwendeten Dateisystem ReiserFS. Das open-source Programm
Partition Image for Linux16 kommt damit aber sehr gut zurecht. Partition
Image ist auch Teil der, ebenfalls frei erhältlichen, System Rescue CD17 . Für
die Sicherung bootet man den entsprechenden PC einfach mit der System
Rescue CD, startet Partition Image und gibt dort den Kompressionsgrad sowie den Image-Namen an. Falls bisher keine weitere Partition zum Ablegen
der Sicherung eingerichtet ist, kann dies mit dem Tool QtParted, das sich
ebenfalls auf der CD befindet, nachgeholt werden.
3.3.4
Kommunikations-Struktur
Die hier betrachtete Struktur steht nur für die Testphase, im realen Betrieb
würde man den bereits vorhandenen Webserver (Apache) des Verwaltungsnetzwerkes verwenden. Er befindet sich im sogenannten Secure Server Net,
gemeinsam mit einigen anderen Servern (z.B. Proxy). Der SuperX-Server
mit Tomcat steht genauso wie der Datenbankserver mit PostgreSQL direkt
im Verwaltungsnetz. Die beiden letztgenannten Systeme könnten auch auf
einem Server betrieben werden. Die Clients würden so die HTTP-Requests
nur an den Apachen senden, welcher sie intern dann weiter reichte. Es entsteht somit keine direkte Kommunikationsverbindung zwischen SuperX- und
Datenbankserver mit den Clients.
Hier stellt sich als nächstes die Frage, für welche Bereiche der Zugriff auf
SuperX erlaubt werden soll. Bei einer universitätsweiten Nutzung von SuperX, bietet es sich an, den Zugriff im kompletten Universitätsnetz (132.230.x.x)
zu erlauben, da Mitarbeiter verschiedenster Einrichtungen Auswertungen
vornehmen sollen. Die Zugriffsfreigabe für beliebige IP-Bereiche, also das
komplette Internet, ist auch denkbar, aber nicht empfehlenswert. Durch die
bereits vorhandene Möglichkeit per VPN-Client (Virtual Privat Network)
16
17
http://www.partimage.org
http://www.sysresccd.org
KAPITEL 3. SUPERX AN DER UNIVERSITÄT FREIBURG
35
Abbildung 3.11: Kommunikations-Struktur für den SuperX-Betrieb
eine Universitäts-IP zu erhalten, wäre der Zugriff also auch von ausserhalb für Mitglieder der Universität gewährleistet. Abbildung 3.11 zeigt die
Kommunikation-Struktur, auf der linken Seite Clients aller Art, die über das
Internet auf SuperX zugreifen, und rechts das Universitätsnetz, beziehungsweise das Verwaltungsnetz mit Clients und den Servern. Client 1-3 stellen mit
Hilfe eines VPN-Tunnels die Verbindung her, der verbreiteste Vertreter der
Tunneling-Protokolle ist IPSec. Die Clients a und b benötigen keinen VPNTunnel, da sie ja bereits eine Universitäts-IP besitzen. Direkt im Intranet der
Verwaltung befinden sich die Clients x,y und z.
Kapitel 4
Mobile SuperX
In Gesprächen mit potentiellen Nutzern von SuperX kam die Frage auf, ob
SuperX auch auf Palm oder Pocket PC nutzbar sei. Mit den bisher vorgestellten Frontends ist dies nicht der Fall. Für das Java-Applet sind aktuelle Geräte
in Bezug auf Rechenleistung und Display bei weitem nicht leistungsfähig genug. Die Anforderungen des XML-Frontends sind ebenfalls deutlich zu hoch
für einen PDA (Personal Digital Assistant), aber es dient als Basis für die
Entwicklung des neuen Frontends Mobile SuperX. Folgendermaßen wurde
dabei vorgegangen:
1. Zuerst muss geklärt werden, welche Technologie verwendet werden soll.
2. Analyse der Technik und der unterstützten Standards.
3. Analyse der vorhandenen Struktur (XML-Frontend).
4. Implementierung von Mobile SuperX.
4.1
Welche Technologie soll verwendet werden?
Man muss sich die Frage stellen für welche Geräte Mobile SuperX bestimmt
sein soll. Handys sind mit Sicherheit weiter verbreitet als PDAs, haben im
Moment aber eine zu geringe Rechenleistung, auch wenn sie stetig erhöht
wird. An den kleinen Displays wird sich allerdings nicht viel verändern, selbst
wenn die Auflösung weiter verbessert wird. Von grossem Vorteil wäre bei der
Entwicklung auch, wenn man auf vertraute und traditionelle Technologien,
wie HTTP (Hypertext Transfer Protocol) und HTML (Hypertext Markup
Language), zurückgreifen kann. Wünschenswert ist also, dass man nicht auf
36
KAPITEL 4. MOBILE SUPERX
37
Spezielleres wie zum Beispiel cHTML (i-mode) und WML (WAP) angewiesen
ist. Bei den beiden zuletzt genannten Technologien ist die Zukunftssicherheit
außerdem nicht unbedingt garantiert. Somit kommt man zu dem Schluss,
dass wenn man große Teile von SuperX “mobil“ machen möchte, PDAs das
richtige Endgerät darstellen, denn sie unterstützen die gewünschten Standards. Dies wird im nächsten Abschnitt genauer erörtert.
4.2
PDAs: Palm und Pocket PC
Zunächst muss eine Analyse durchgeführt werden, welche für Geräte aktuell
auf dem Markt sind und was diese zu leisten im Stande sind. Der Markt
teilt sich zum jetzigen Zeitpunkt in zwei große Gruppen auf, Gruppe eins
sind PDAs mit PalmOS1 als Betriebssystem, Gruppe zwei arbeitet mit der
mobilen Version von Micosofts Windows2 (aktuell: Windows Pocket 2003).
Flaggschiffe unter den Palms sind der Tungsten C und Tungsten T5. Sonys
Clie Reihe setzt ebenfalls auf PalmOS. Pocket PCs werden von den verschiedensten Herstellern produziert, zum Beispiel von Dell, Fujitsu-Siemens,
Asus und Hewlett-Packard. Die meisten Geräte verfügen über 64-128MB
Hauptspeicher und verwenden spezielle Intel-Prozessoren, welche bereits bis
zu 630MHz erreichen. Es steht also durchaus leistungsstarke Hardware zur
Verfügung, zwei weitere Fragen drängen sich allerdings auf:
• Mit Hilfe welcher Übertragungstechnik soll SuperX auf den PDA gelangen?
• Wie kann SuperX auf dem PDA dargestellt werden?
Die nächsten beiden Abschnitte beantworten diese Fragen.
4.2.1
Standards für drahtlose Netzewerke
Es gibt mehrere Möglichkeiten, einen PDA mit dem SuperX-Server zu verbinden. Das ganze sollte IP-basiert (TCP/IP) sein und mit den vorhandenen
Strukturen (Technologien aus Kapitel 4.1: HTTP und HTML) zusammenarbeiten. Ebenfalls klar ist, dass der PDA eine Wireless LAN-Verbindung
nutzen sollte. Wireless LAN steht hier als Sammelbegriff für verschiedene
drahtlose Netzwerke, wird aber häufig direkt in Verbindung mit dem IEEE
802.11 Standard genannt.
1
2
http://www.palmsource.com/de/palmos/
http://www.microsoft.com/germany/mobile/default.mspx
KAPITEL 4. MOBILE SUPERX
38
IEEE 802.11
Der WLAN-Standard IEEE 802.11 ist der am weitesten verbreitetste. Die
Versionen 802.11b (11MBit/s) und 802.11g (54MBit/s) werden momentan
am häufigsten eingesetzt. Viele PDAs besitzen standardmässig bereits 802.11b
Unterstützung. Falls nicht, kann, wenn ein SD-Karten-Slot vorhanden, mit
einer WLAN-SD-Karte nachgerüstet werden. Die inzwischen hohe Anzahl
von Access Points im drahtlosen Netz der Universität Freiburg, so zum Beispiel auch im Sitzungs- und Senatssaal des Rektoratsgebäudes, macht 802.11
zur idealen Übertragungstechnik für PDAs. Eine aktuelle Liste aller Access
Points findet sich auf der unten angegebenen Webseite3 . Aber auch ausserhalb der Universität ist bereits in vielen Gebäuden und Gebieten WLANEmpfang möglich.
Über eine Ad-hoc-Verbindung zu einem PC kann ein PDA ebenfalls auf
das Internet zugreifen (siehe Abbildung 4.2). Allerdings muss man dafür die
IP-, Gateway- und DNS-Server-Einträge in den Netzwerkeinstellungen des
PDAs richtig konfigurieren, sofern auf dem PC kein DHCP-Server läuft.
Bluetooth
Eine sehr neue Technologie stellt Bluetooth dar. Die Firmen Ericsson, Nokia, IBM, Intel und Toshiba haben sich im Jahr 2000 zu der Bluetooth Special
Interest Group zusammengeschlossen und entwickeln seither gemeinsam an
dem neuen Standard[14]. Die Mehrzahl der aktuellen PDAs, aber auch bereits viele Handys, verfügen über eine Bluetooth-Schnittstelle. Im Gegensatz
zum IEEE 802.11 Standard unterstützt Bluetooth nur eine Datenrate von 1
MBit/s. Die Reichweite beträgt bis zu 20 m, deshalb spricht man in diesem
Zusammenhang auch von einem Wireless Personal Area Network (WPAN).
Ein Vorteil gegenüber 802.11 liegt in der geringeren Stromaufnahme.
Mit Hilfe eines Bluetooth-to-LAN Access Points könnte man einen Raum
auch nur nach Bedarf ausstatten. Zum Beispiel für Besprechungen in denen
mehrere Personen per PDA auf Mobile SuperX zugreifen möchten (siehe
Abbildung 4.1).
Infrarot
Infrarot hat seine Ursprünge bereits im Jahr 1979, aber erst 1993 schlossen
sich circa 30 Firmen zu der Infrared Data Association (IrDA) zusammen.
IrDA nennt man heute auch den Infrarot-Kommunikationsstandard. Die Datenrate beträgt bis zu 16 MBit/s, wobei Entfernungen von nur bis zu 1 m
3
http://www.rz.uni-freiburg.de/netzdl/standorte.html
KAPITEL 4. MOBILE SUPERX
39
Abbildung 4.1: Ein Bluetooth Access Point verbindet PDAs mit dem LAN.
überbrückt werden können[14]. Effektiv müssen zwei Infrarotgeräte sich direkt gegenüber stehen, um eine Verbindung einzugehen, was die Bedienung
des PDAs doch etwas unpraktisch macht. Man spricht hier ebenfalls von
WPANs.
Handy als Modem
Nicht ein Standard, aber eine weitere Möglichkeit, mit einem PDA eine Internetverbindung herzustellen, ist ein Handy als Modem zu nutzen. Dafür wird
entweder über Bluetooth oder IrDA eine Verbindung zum Handy hergestellt,
welches sich dann mit Hilfe der Mobilfunkttechnik (z.B. GPRS oder UMTS)
beim jeweiligen Mobilfunkanbieter einwählt (siehe Abbildung 4.2). Die Mobilfunkanbieter stellen dafür spezielle Konfigurationsdaten und Einwahlnummern zur Verfügung. Abgerechnet wird entweder nach Transfervolumen oder
nach Zeit, bei T-Mobile kosten derzeit zum Beispiel 10 MB und 2 Stunden jeweils 10 Euro. Damit ließen sich schon sehr viele SuperX-Abfragen
durchführen. Sofern man Bluetooth nutzt, kann man auf Grund der recht
hohen Reichweite das Bluetooth-Handy einfach eingeschaltet in der Tasche
lassen.
Sicherheit
Bei der Einwahl in das WLAN der Universität wird eine verschlüsselte Verbindung zwischen dem mobilen Gerät und einem Server des Rechenzentrums
aufgebaut. Zum Aufbau des VPN-Tunnels (Virtual Private Network ) wird ein
VPN-Client benötigt. Die Verbindung kommt nur mit einer gültigen Universitätskennung und entsprechender Authentifizierung zustande. Die meisten
Palms und Pocket PCs enthalten beim Kauf bereits einen VPN-Client, man
KAPITEL 4. MOBILE SUPERX
40
Abbildung 4.2: Es gibt verschiedene Möglichkeiten einen PDA mit dem Internet zu verbinden.
kann sie aber auch separat nachinstallieren (z.B. Mergic VPN4 für Palm OS,
movianVPN5 für Windows Mobile). Somit braucht man sich über die Sicherheit keine weiteren Sorgen mehr zu machen. Wie bereits in Kapitel 3.3.4
beschrieben wird damit auch eine Universitäts-IP zugwiesen, was auch den
Zugriff auf den für SuperX zuständigen Webserver erlaubt.
4.2.2
Darstellung und Browsertechnik
Um die Darstellungsmöglichkeiten von SuperX auf PDAs zu analysieren,
muss man sich einerseits über das Display und andererseits auch über den
verwendeten Browser Gedanken machen.
Display
Erfreulicherweise sind die aktuellen PDAs mit sehr leistungsfähigen Farbdisplays ausgestattet, so hat der Tungsten C zum Beispiel eine Auflösung von
320x320, der T3 und T5 sogar 320x480. Dies ist durchaus ausreichend, um
kleinere Tabellen übersichtlich darzustellen. Probleme ergeben sich logischerweise bei grossen Seiten.
Browser für PDAs
Wer schon einmal eine Internetseite designt hat, der hat sich sicherlich über
die vielen Eigenarten der Internetbrowser geärgert. Für PDAs sieht es noch
4
5
http://www.mergic.com
http://www.movianvpn.com
KAPITEL 4. MOBILE SUPERX
41
um einiges schlimmer aus. Es existiert eine Vielzahl von verschiedenen Browsern, welche mehr oder weniger regelmässig weiterentwickelt werden. Selbst
einfachste HTML-Seiten werden auf unterschiedlichen Browsern sehr verschieden dargestellt. Besonders problematisch ist die Darstellung von Tabellen, Frames, Bildern und verschiedenen Schriftarten. Der fortschrittlichste
Browser ist NetFront 3.1 von der japanischen Firma Access6 , der Gewinner
des “Pocket PC Awards Best Internet Browser“. Er ist für Pocket PC, Palm
und diverse andere mobile Plattformen verfügbar. Allerdings versteckt er sich
im PalmOS hinter dem Namen PalmSource Web Browser [12].
NetFront unterstützt viele wichtige Wireless- und Internet-Standards[13],
für uns wichtig sind folgende:
• HTML 4.01
• XHTML 1.1
• CSS 1, CSS 2
• HTTP 1.1 und TCP/IP
• ECMAScript (Javascript 1.5)
• SSL v3.0
Wobei man hier in der Weise einschränken muss, dass nicht alle Funktionen eines Standard tatsächlich unterstützt werden (z.B. bei JavaScript).
NetFront und alle anderen PDA-Browser haben gemeinsam, dass sie natürlich
nicht an die Darstellungsqualität eines PC-Browsers herankommen. Die Hauptaufgabe liegt darin, die Webseite auf den kleinen Displays ordentlich aufbereitet anzuzeigen. Dafür werden die Seiten zunächst übertragen und dann intern
in ein passendes Format transformiert. Dies führt dazu, dass sich der Seitenaufbau etwas verzögert und das Layout vom Original (PC-Browser) teilweise
doch deutlich abweicht. Die Gestaltung des Designs wird dadurch natürlich
nicht gerade einfacher, andererseits erzielen die PDA-Browser, insbesondere
NetFront, doch ganz erstaunlich gute und übersichtliche Ergebnisse (siehe
Abbildung 4.3 und 4.4).
4.3
Das XML-Frontend als Basis
Nach den Vorüberlegungen kristallisiert sich langsam ein Bild von dem neuen
Frontend heraus. Wichtig ist, dass die Rechenlast größtenteils auf Seiten
6
http://www.access.co.jp
KAPITEL 4. MOBILE SUPERX
Abbildung 4.3: Recht übersichtlich: ntv.de mit NetFront ...
42
Abbildung 4.4: ... und etwas weiter
nach rechts gescrollt
des Servers liegt und dass das Layout sich an den kleinen PDA-Displays
orientiert. Als Technologie bietet sich HTML dafür sehr gut an. Ziel ist also,
alle Berechnungen auf dem Server durchzuführen und nur kleine HTMLDateien mit den Ergebnissen an die PDAs zusenden. Wenn man nun das
XML-Frontend betrachtet, stellt man fest, dass dieses den Anforderungen
für Mobile SuperX grundsätzlich schon recht nahe kommt.
Bevor man jedoch an die Entwicklung von Mobile SuperX geht, muss man
zunächst analysieren, wie das XML-Frontend arbeitet, welche Technologien
darin verwendet werden und wie diese funktionieren. Zwei Arten von Dateien
benötigen wir dazu:
1. die Java-Dateien für das Servlet aus dem Verzeichnis:
home/superx/webserver/tomcat/webapps/superx/WEB-INF/src/de/
superx/servlet
2. und die XSL-Dateien zur Darstellung des XML-Stromes aus dem Verzeichnis: home/superx/webserver/tomcat/webapps/superx/xml.
Servlets sind im Grunde nichts anderes als Java-Klassen, die serverseitig laufen. Sie belasten also die Clients, im Gegensatz zu Applets, nicht, was
natürlich für PDAs besonders wichtig ist. Aufgrund ihrer Vorteile (z.B. Plattformunabhängigkeit und Leistungsfähigkeit) sind sie sehr gut als Ersatz für
klassische CGI-Programme (z.B. Perl) zu gebrauchen. Mit Servlet Container
bezeichnet man die Java Virtual Machine, welche die Servlets hostet[16], für
SuperX verwenden wir, wie bereits gesehen, Apache Jakarta Tomcat. Servlets
KAPITEL 4. MOBILE SUPERX
43
sind nicht zu verwechseln mit Java Server Pages (JSP). Weitere Einzelheiten
zu Servlets werden später direkt am Quellcode von Mobile SuperX erläutert.
Die Extensible Stylesheet Language (XSL) ist eine Spezifikation des World
Wide Web Consortiums (W3C)7 und besteht aus drei Teilen: XSL Transformations (XSLT), XML Path Language (XPath) und XSL Formatting Objects (XSL-FO). Aufgabe von XSLT ist es, XML zu transformieren und zwar
entweder in HTML, in XML oder in Text. Konkret werden bei SuperX XMLDokumente durch die Servlets erzeugt, welche mittels eines XSLT-Prozessors
in für die Browser darstellbares HTML umgewandelt (transformiert) werden.
Im Servlet wird angegeben, welches Stylesheet für den jeweilgen XML-Strom
verwendet werden soll. Ähnlich wie bei PHP bemerkt der Anwender (Client)
davon überhaupt nichts, da er nur das “fertige“ HTML-Dokument von Server zugesendet bekommt. Mehr als nur ein schönes Beiwerk hierbei ist die
Trennung von Inhalt und Design.
Die Implementation von Mobile SuperX wird in Kapitel 4.5 beschrieben,
wobei das XML-Frontend als Basis dafür verwendet wird.
4.4
Test- und Enwicklungsumgebung
Ein Notebook (Pentium 3, 1 GHz, 256 MB Ram) mit WLAN-Karte diente
in der Testumgebung als Datenbank- und Webserver, wobei auf die SSLEinrichtung sowie auf die Verbindung zum Apache der Einfachheit halber
verzichtet wurde. Auf dem Notebook läuft zusätzlich ein DHCP-Server. Den
Zweck des mobilen Endgerätes erfüllte ein Palm Tungsten C, welcher standardmäßig über Wireless Lan und Infrarot-Schnittstelle verfügt. Auf Softwareseite wartet er mit Palm OS 5.2.1 und dem Palm Web Browser 2.0 auf, in
diesem versteckt sich der Kern von NetFront 3.0[12]. Die Verbindung zwischen Server und Palm wird direkt über ein Ad-hoc-Netzwerk hergestellt,
also peer-to-peer ohne extra Access-Point. Abbildung 4.5 zeigt die beschriebene Umgebung Anmerkung: In Kapitel 4.6 werden weitere Konfigurationen
(Pocket PC, verschiedene Browser) getestet und vorgestellt.
Für die Kompilierung der Java Servlet-Klassen wurde Java 2 SDK verwendet, teilweise wurde zusätzlich das FOP-Paket8 der Apache Group benötigt.
Die Editoren jEdit9 und Kate dienten zur Entwicklung. Mit XML-Spy10 wurde eine weitere Entwicklungsumgebung für XSL-Stylesheets getestet.
7
http://www.w3.org/Style/XSL/
http://xml.apache.org/fop/
9
http://www.jedit.org/
10
http://www.altova.com/de/products ide.html
8
KAPITEL 4. MOBILE SUPERX
44
Abbildung 4.5: Die Testumgebung für die Entwicklung von Mobile SuperX
4.5
Implementation
Im Folgenden wird nun beschrieben, wie Mobile SuperX implementiert wird.
Dabei wird auch auf Quellcode des XML-Frontends zurückgegriffen und dabei dieser abgeändert oder erweitert. SuperX ist ein Open-Source-Projekt, in
diesem Sinne soll das Frontend Mobile SuperX das System ebenfalls erweitern. Folgende Ziele sind bei der Entwicklung zu verfolgen:
• Auf Frames muss verzichtet werden. Sie werden zwar von manchen
PDA-Browsern unterstützt, jedoch geht dies auf Kosten der Übersichtlichkeit.
• Es sollte sich auf das Wesentliche konzentriert werden, also sollten keine
HTML-Inhalte einfügen werden, die nicht dem Inhalt oder der Navigation gelten.
• Die Bedienung sollte einfach und intuitiv sein.
• Durch den Einbau einer Navigationsleiste soll Mobile SuperX auch im
Vollbildmodus bedienbar sein.
• Auf Texteingaben sollte nach Möglichkeit verzichtet werden, diese sind
mit einem PDA - auch wenn der Tungsten C eine kleine Tastatur hat
- doch sehr mühsam.
• Das Layout sollte auf allen Browsern gleich oder zumindest ähnlich
dargestellt werden.
• Das Menü ist nicht auf einer Seite darstellbar wie beim XML-Frontend
(siehe Abbildung 4.6) und muss deshalb in zwei Seiten aufgeteilt werden. Im ersten Menü soll der gewünschte Bereich ausgewählt werden,
im zweiten die zugehörigen Abfrage.
KAPITEL 4. MOBILE SUPERX
Abbildung 4.6: Das XML-Frontend von SuperX
45
KAPITEL 4. MOBILE SUPERX
46
• Spezielle, auf PDAs zugeschnittene Funktionen sollen die Übersichtlichkeit verbessern und die Bedienung erleichtern.
Auf Grund der teilweisen Verwendung des XML-Frontends muss man sich
über folgende Punkte keine Gedanken mehr machen und kann diese übernehmen:
• Authentifizierung in SuperX
• DB-Verbindung mit PostgreSQL (oder anderen DB-Systemen)
• Servlets, die im Hintergrund arbeiten (z.B. SuperX el)
4.5.1
Anmeldung
Für die Anmeldung genügt eine einfache HTML-Datei, die man index.htm
tauft und im Ordner ../tomcat/webapps/superx/mobile ablegt. Zentrales
Element ist ein Formular, welches zur Eingabe der Kennung und des Passwortes dient. Die Variablen dafür heissen kennung und passwort und werden
per HTTP-POST an das Servlet MobileSuperxAnmeldung gesendet.
Listing 4.1: index.html
< html >
< head >
< title > Mobile SuperX </ title >
< link REL =" stylesheet " type =" text / css " href ="../ style /
• pda . css "/ >
</ head >
< body bgcolor ="# C7E6FE " >
< center >
< table border ="1" bordercolor =" black " width ="260"
• cellspacing ="0" >
<td >
<h3 >  Mobile Superx Anmeldung </ h3 >
< form action ="../ servlet / M obile Supe rxAn meldu ng " method ="
• post " >
<p >  < input type =" Text " name =" kennung " value ="" > </
• p>
<p >  < input type =" Password " name =" passwort " value
• ="" > </ p >
  < input type =" Submit " name =" Abschicken " value
• =" Anmelden " >
KAPITEL 4. MOBILE SUPERX
47
Abbildung 4.7: Anmeldung für Mobile SuperX im Palm Web Browser
</ form >
<p >  < a href ="../ index . htm " > zur SuperX - Startseite </ a
• >
&# 16 0; &# 16 0; &# 16 0;
<a href =" hilfe . html " > Hilfe </ a > </p >
</ td >
</ table >
</ center >
</ body >
</ html >
Das Ergebnis des HTML-Dokuments sieht man in Abbildung 4.7.
Servlet für die Anmeldung
Nun kommt das Servlet MobileSuperxAnmeldung, dessen Aufgabe unter anderem der Aufbau des ersten Menüs ist. Zuerst wird das Servlet dem Paket
de.superx.servlet zugeordent und die benötigten Klassen werden eingebunden:
Listing 4.2: MobileSuperxAnmeldung.java
package de . superx . servlet ;
// File : M o b i l e S u p e r xAn meldu ng . java
import javax . servlet .*;
import javax . servlet . http .*;
KAPITEL 4. MOBILE SUPERX
import
import
import
import
import
import
import
import
import
import
48
java . net . InetAddress ;
java . io .*;
java . util .*;
java . sql .*;
javax . xml . transform . Transformer ;
javax . xml . transform . TransformerFactory ;
javax . xml . transform . Source ;
javax . xml . transform . stream . StreamSource ;
javax . xml . transform . stream . StreamResult ;
de . superx . util .*;
Unser Servlet erweitert die HttpServlet Klasse:
/*
*
@author Christoph Litz , basierend auf SuperX - XML • Frontend ( Supe rXmlAnmeldung )
von Fa . Memtext
*
*/
public class M o b i l e S u p e rxAn meldu ng extends HttpServlet {
public static Logger my_logger ;
ResourceBundle rb = ResourceBundle . getBundle ("
• LocalStrings ") ;
String db_driver = "";
String client_ip = "";
String client_dns = "";
/**
* Diese Methode wird verwendet , wenn das Servlet
• das erste mal geladen wird .
*/
public void init ( ServletConfig config ) throws
• ServletException {
super . init ( config ) ;
my_logger = new Logger () ;
ServletUtils . init_logging ( config , my_logger ) ;
Die Methode doPost() überschreibt die vom HttpServlet geerbte. Sie wird
jedes Mal aufgerufen, wenn der Webserver ein POST-Request von einem Client erhält. Hier wird also festgelegt, wie das Servlet mit POST-Requests, die
durch HttpServletRequest repräsentiert werden, umgeht[16].
HttpServletRequest gibt dem Servlet die Informationen über den Client,
welche im HTTP-Header stehen. HttpServletResponse repräsentiert die
Antwort des Servlets. Dieses Objekt wird dazu verwendet, Daten zurück
zum Client zu schicken. Zu Beginn benötigt man zahlreiche Variablen, dabei
werden auch die Parameter kennung und passwort eingelesen:
KAPITEL 4. MOBILE SUPERX
49
/**
* Jedes Mal wenn der Webserver ein POST - Request
• fur dieses Servlet erhaelt ,
* ruft er die doPost () Methode auf .
*/
public void doPost ( HttpServletRequest request ,
• H tt p S e rv l e tR e sponse response ) throws
• ServletException , IOException {
SuperX_el aSuperX_el = null ;
PrintWriter out = null ;
BufferedReader inTest = null ;
SuperX_el gesamt = new SuperX_el () ;
Integer userid = new Integer ( -1) ;
Short adminUser = new Short (( short ) 0) ;
String login_name = " null ";
String user = "";
String passwort = "";
String passwd_sha = "";
SxSQL_Server aQuery = null ;
String xml = "";
Vector a u t h e n t icationVector = null ;
String query ;
Vector rows = new Vector () ;
Vector zeilenobjekt = new Vector () ;
Cookie userCookie ;
user = ( String ) request . getParameter (" kennung ") ;
passwort = ( String ) request . getParameter ("
• passwort ") ;
client_dns = ( String ) request . getParameter ("
• Remote Host ") ;
String msg_denied = rb . getString (" superx . denied ") ;
HttpSession session = request . getSession ( true ) ;
my_logger . log (" conn " ," Session - Timeout :"+ session .
• g e t M a x I n a ct iv eI nte rv al () ) ;
ConnectionPool poolConnection = null ;
Connection dbConnection = null ;
long callerId = IDGenerator . getInstance () . getID
• () ;
Jetzt kann man die Datenbankverbindung für die aktuelle Anfrage aus dem
Pool holen:
try {
KAPITEL 4. MOBILE SUPERX
50
aQuery = new SxSQL_Server ( my_logger ) ;
poolConnection = ConnectionPool . getInstance (
• my_logger ) ;
db_driver = poolConnection . m_DriverClass ;
dbConnection = poolConnection . getConnection (
• callerId , this ) ;
a u t h e n t i c a tionVector =
authenticate (
aQuery ,
my_logger ,
dbConnection ,
gesamt ,
user ,
passwort ) ;
userid = ( Integer ) authenticationVector .
• elementAt (0) ;
login_name = ( String ) authenticationVector .
• elementAt (1) ;
passwd_sha = ( String ) authenticationVector .
• elementAt (2) ;
adminUser = ( Short ) authenticationVector .
• elementAt (3) ;
}
catch ( DB Se rv letException de ) {
my_logger . log (
" sql " ,
" DBServletException - Exception : " + de .
• toString () ) ;
gesamt . setError_String ( de . toString () ) ;
} catch ( Exception e ) {
my_logger . log (" sql " , " Exception : " + e .
• toString () ) ;
gesamt . setError_String ( e . toString () ) ;
} finally {
if ( poolConnection != null && dbConnection
• != null ) {
my_logger . log (" conn " , " Verbindung
• erfolgreich ") ;
} else {
my_logger . log (" conn " , " Fatal error ....")
• ;
}
KAPITEL 4. MOBILE SUPERX
51
}
my_logger . log (" conn " , " User tries to log in ") ;
Als Nächstes wird damit begonnen, den XML-String aufzubauen. Er beginnt
mit dem Tag <menue>. Zuvor muss allerdings noch geprüft werden, ob es sich
überhaupt um eine gültige Authentifizierung handelt.
xml += " < menue >";
if ( login_name . equals (" null ") || userid == null ) {
my_logger . log (" conn " , " User not logged in ") ;
try {
xml += ServletUtils . Login_failure (
• msg_denied , rb . getString (" superx .
• logintext ") , rb . getString (" superx . login
• ") , user ) ;
}
catch ( Exception e )
{
xml +=" < nachricht > Keine G l t i g e
• Authentifizierung </ nachricht >";
}
session . setAttribute ( " UserID " ," false ") ;
session . setAttribute ( " password " ,"") ;
}
Ist alles korrekt, werden die UserID und das Passwort in die aktuelle Session
geschrieben. Dem XML-String wird eine Nachricht hinzugefügt:
else {
session . setAttribute ( " UserID " , userid .
• toString () ) ;
session . setAttribute ( " password " , passwd_sha
• );
xml += " < user >"+ user +" </ user >";
xml += " < nachricht > Willkommen " + login_name
• + " </ nachricht >";
Je nach verwendeter Datenbank, beziehungsweise DB-Treiber, wird nun die
SQL-Anfrage (query) als String zusammengebaut. In der Tabelle tmp themenbaum
stehen die Eigenschaften der einzelnen Abfragen, diese sind:
• tid: Jede Abfrage hat eine eindeutige Transaktion-ID.
KAPITEL 4. MOBILE SUPERX
52
• name: Name der Abfrage, wie sie im Menü tatsächlich erscheint (z.B.
“Benutzer von SuperX“).
• maskeninfo id: Gibt an, welche Maske für die Abfrage verwendet wird.
• parent: Vorgänger des Themenpunktes (z.B. ist “Administration“ parent von “Benutzer von SuperX“).
• erlaeuterungen: Beschreibung der Abfrage, braucht man für Mobile SuperX momentan eigentlich nicht.
Auch wenn in Zukunft nur noch PostgreSQL verwendet werden wird, sollte
man die Informix-Treiber sowie eine weitere Alternative trotzdem im Code
belassen.
// Rohfassung ( vector in vector ) aus DB
java . util . Date date = new java . util . Date () ;
if ( db_driver . equals (" org . postgresql . Driver
• ") ) {
// postgres
query =" select sp_user_themen ("+ userid .
• toString () +" , today () ,1) ; select
• distinct tid , name , maskeninfo_id ,
• parent , erlaeuterung from
• tmp_themenbaum ;";
} else {
if ( db_driver . equals (" com . informix . jdbc .
• IfxDriver ") ) {
// informix
query =" execute procedure
• sp_user_themen ("+ userid .
• toString () +" , today ,1) ; select
• distinct tid , name , maskeninfo_id
• , parent , erlaeuterung from
• tmp_themenbaum ;";
} else {
query =
" select tid , name , maskeninfo_id
• , parent , gueltig_seit ,
• gueltig_bis from themenbaum
• order by name ;";
}
}
KAPITEL 4. MOBILE SUPERX
53
Nun werden alle Queries ausgeführt und die User-ID an den XML-String
gehängt:
try {
my_logger . log (" sql " , " Abfrage : " + query
• );
aQuery . executeALL ( query , dbConnection ,
• gesamt ) ;
xml += " < userid >"
+ userid . toString ()
+ " </ userid >";
An dieser Stelle werden jetzt die Einträge für das Menü an den XML-String
gehängt. Dabei wird jede Zeile, repräsentiert durch einen Vektor, der ErgebnisTabelle des Querys einzeln in die Hand genommen. Die Elemente des Vektors
werden dann zwischen die entsprechenden XML-Tags geschrieben (ein Beispiel XML-Dokument in dieser Form ist weiter unten zu finden):
int numberOfColumns = gesamt .
• getColumnCount () ;
rows = gesamt . getRows () ;
xml += " < eintraege >";
for ( int zeile = 0; zeile < rows . size () ;
• zeile ++) {
zeilenobjekt = ( Vector ) rows .
• elementAt ( zeile ) ;
xml += " < eintrag > < zeile >"
+ ( zeile + 1)
+ " </ zeile > < id >"
+ zeilenobjekt . elementAt (0)
+ " </ id > < tid >"
+ zeilenobjekt . elementAt (2)
+ " </ tid > < titel >"
+ zeilenobjekt . elementAt (1)
+ " </ titel > < parent >"
+ zeilenobjekt . elementAt (3)
+ " </ parent > </ eintrag >";
}
xml += " </ eintraege >";
poolConnection . returnConnection ( callerId
• , this ) ;
KAPITEL 4. MOBILE SUPERX
54
Danach werden noch die Exceptions abgefangen und das XML-Dokument
mit </menue> korrekt geschlossen.
} catch ( SQLException e ) {
my_logger . log (" sql " , e . toString () ) ;
gesamt . setError_String ( e . getSQLState () ) ;
}
}
xml += " </ menue >";
my_logger . log (" sql " , " xml - Stream : " + xml ) ;
PrintWriter output = response . getWriter () ;
Jetzt kann man das Stylesheet angeben, welches den XML-Strom in HTML
transformieren soll. Man könnte noch den User Agent im HTTP-Header auslesen und ein zum Browser passendes Stylesheet angeben, so wie es beim
XML-Frontend geschiet. Dies macht für Mobile SuperX momentan allerdings keinen Sinn, da die User-Agents oft nicht aussagekräftig genug versandt
werden[20].
try {
String Stil = " mobile / mobile_menu . xsl ";
response . setContentType (" text / html ; charset =
• ISO -8859 -1") ;
Zum Abschluss wird die XML-Deklaration noch an Beginn des XML-Strings
geschrieben und anschließend alles transformiert:
javax . xml . transform . TransformerFactory
• tFactory =
javax . xml . transform . TransformerFactory .
• newInstance () ;
javax . xml . transform . Transformer transformer
• =
tFactory . newTransformer (
new javax . xml . transform . stream .
• StreamSource (
" file :///"
+ getServletConfig () .
• getServletContext () .
• getRealPath (
Stil ) ) ) ;
KAPITEL 4. MOBILE SUPERX
55
StringReader s1 = new StringReader (" <? xml
• version = ’1.0 ’ encoding = ’ ISO -8859 -1 ’? >"+
• xml ) ;
transformer . transform (
new javax . xml . transform . stream .
• StreamSource ( s1 ) ,
new javax . xml . transform . stream .
• StreamResult ( output ) ) ;
}
Und wiederum werden Exceptions abgefangen:
catch ( Exception e ) {
my_logger . log (
" sql " ,
" Es ist ein Fehler entstanden ..."
+ e . toString () ) ;
response . setContentType (" text / html ; charset =
• ISO -8859 -1") ;
output . println ( de . superx . servlet .
• ServletUtils . xml_fehler ( e . toString ()
• , xml ) ) ;
}
}
Damit auch GET-Requests beantwortet werden können, wird die Methode
doGet() verwendet. Sie soll einfach genau dasselbe machen wie doPost().
public void doGet ( HttpServletRequest request ,
• H tt p S e rv l e tR e sponse response )
throws ServletException , IOException {
doPost ( request , response ) ;
}
An dem nun folgenden Abschnitt sind glücklicherweise keine Veränderungen
nötig, er wird deshalb eins zu eins aus SuperXmlAnmeldung.java übernommen und hier nur der Vollständigkeit wegen aufgeführt. Wichtigster Inhalt ist
der Authentifizierungs-Vektor und bei diesem können wir alles so belassen,
wie es auch im XML-Frontend ist.
public String getServletInfo () {
return " <i > MobileSuperxAnmeldung - Servlet </ i >";
}
KAPITEL 4. MOBILE SUPERX
56
public void buildMenu (
Connection dbConnection ,
Integer userid ) {
Vector rows = new Vector () ;
SuperX_el gesamt = new SuperX_el () ;
String query = "";
}
private Vector authenticate (
SxSQL_Server myQuery ,
Logger myLogger ,
Connection myConnection ,
SuperX_el myRecordset ,
String user ,
String passwort ) {
Vector rows = new Vector () ;
String username ;
Vector ergebnis = new Vector () ;
Integer userid ;
String password_sha ;
Short noAdmin = new Short (( short ) 0) ;
Short administrator = new Short (( short ) 0) ;
InetAddress client_addr = null ;
String client_ip = null ;
InetAddress client_dns = null ;
int proto_fkt_id = 2; // LOGIN_FAIL
int proto_id_pos = -1;
int user_id_pos = -1;
StringBuffer prot_sql = new StringBuffer () ;
prot_sql . append (" insert into protokoll (
• proto_fkt_id , userinfo_id , ") ;
prot_sql . append (" ip_adresse , client_name ,
• zeitpunkt ) values (") ;
prot_sql . append ("? , ") ;
prot_sql . append (" -1 , ’ Not available ’") ;
prot_sql . append (" , ’" + client_dns + " ’") ;
if ( db_driver . equals (" org . postgresql . Driver ") ) {
prot_sql . append (" , now () ) ;") ;
} else {
prot_sql . append (" , current ) ;") ;
}
KAPITEL 4. MOBILE SUPERX
57
proto_id_pos = prot_sql . toString () . indexOf ("?") ;
prot_sql . replace (
proto_id_pos ,
proto_id_pos + 1 ,
( new Integer ( proto_fkt_id ) ) . toString () ) ;
String query =
" select tid , passwd_sha , administration ,
• name "
+ " from userinfo where benutzer = ’"
+ user
+ " ’;";
try {
myLogger . log (" sql " , " Abfrage : " + query ) ;
myQuery . executeQuery ( query , myConnection ,
• myRecordset ) ;
} catch ( SQLException se ) {
myLogger . log (" sql " , " SQL - Fehler : " + se .
• toString () ) ;
user_id_pos = prot_sql . toString () . indexOf
• ("%") ;
if ( user_id_pos > 0)
prot_sql . replace ( user_id_pos ,
• user_id_pos + 1 , " -1") ;
try {
myQuery . execute ( prot_sql . toString () ,
• myConnection , myRecordset ) ;
} catch ( SQLException e1 ) {
myLogger . log (
" sql " ,
" SQL - Fehler : "
+ prot_sql . toString ()
+ "\ n "
+ e1 . toString () ) ;
}
} catch ( Exception e ) {
myLogger . log (" sql " , " DB - Zugriff - Fehler : " +
• e . toString () ) ;
}
rows = myRecordset . getRows () ;
if ( rows . size () > 0) {
query =
KAPITEL 4. MOBILE SUPERX
58
" select tid , passwd_sha , administration ,
• name "
+ " from userinfo where benutzer =
• ’"
+ user
+ " ’ and akt_versuch < max_versuch
• ;";
try {
myLogger . log (" sql " , " Abfrage : " + query )
• ;
myQuery . executeQuery ( query , myConnection
• , myRecordset ) ;
} catch ( SQLException se ) {
myLogger . log (" sql " , " SQL - Fehler : " + se .
• toString () ) ;
user_id_pos = prot_sql . toString () .
• indexOf ("%") ;
if ( user_id_pos > 0)
prot_sql . replace ( user_id_pos ,
• user_id_pos + 1 , " -1") ;
try {
myQuery . execute (
prot_sql . toString () ,
myConnection ,
myRecordset ) ;
} catch ( SQLException e1 ) {
myLogger . log (
" sql " ,
" SQL - Fehler : "
+ prot_sql . toString ()
+ "\ n "
+ e1 . toString () ) ;
}
} catch ( Exception e ) {
myLogger . log (" sql " , " DB - Zugriff - Fehler :
• " + e . toString () ) ;
}
if ( myRecordset != null )
{
rows = myRecordset . getRows () ;
if ( rows . size () > 0) {
KAPITEL 4. MOBILE SUPERX
59
Vector zeilenobjekt = ( Vector ) rows .
• elementAt (0) ;
userid = ( Integer ) zeilenobjekt .
• elementAt (0) ;
username = zeilenobjekt . elementAt (3) .
• toString () ;
// MB MiniSuperX
// Original : adminUser = ( Short ) V_row .
• elementAt (2) ;
// die Informix - Datenbank liefert eine
• Short - Wrapper
// Access dagegen einen Integer - Wrapper ,
• muss
// ggfs . konvertiert werden
try {
// normal Informix
administrator = ( Short ) zeilenobjekt
• . elementAt (2) ;
} catch ( ClassCastException e ) {
// Access liefert Integer - Wrapper
Integer dummy = ( Integer )
• zeilenobjekt . elementAt (2) ;
Short dummy2 = new Short (( short )
• dummy . shortValue () ) ;
administrator = dummy2 ;
}
// Ende Mini SuperX
password_sha = ( String ) zeilenobjekt .
• elementAt (1) ;
String encoded_sha = SqlStringUtils .
• encode_sha ( passwort ) ;
if ( password_sha . equals ( encoded_sha ) ) {
ergebnis . add ( userid ) ;
ergebnis . add ( username ) ;
ergebnis . add ( password_sha ) ;
ergebnis . add ( administrator ) ;
query =
" update userinfo set akt_versuch
• =0 "
+ " where benutzer = ’"
+ user
+ " ’ and akt_versuch >0;";
KAPITEL 4. MOBILE SUPERX
60
try {
myLogger . log (" sql " , " Abfrage : "
• + query ) ;
myQuery . execute ( query ,
• myConnection , myRecordset ) ;
} catch ( SQLException se ) {
myLogger . log (" sql " , " SQL - Fehler :
• " + se . toString () ) ;
} catch ( Exception e ) {
myLogger . log (
" sql " ,
" DB - Zugriff - Fehler : " + e .
• toString () ) ;
}
} else {
myLogger . log (
" sql " ,
" Authentifizierung
• fehlgeschlagen ; Passwort • Klartext : "
+ passwort ) ;
ergebnis . add ( null ) ;
ergebnis . add (" null ") ;
ergebnis . add (" null ") ;
ergebnis . add ( noAdmin ) ;
query =
" update userinfo set akt_versuch
• = akt_versuch +1 "
+ " where benutzer = ’"
+ user
+ " ’;";
try {
myLogger . log (" sql " , " Abfrage : "
• + query ) ;
myQuery . execute ( query ,
• myConnection , myRecordset ) ;
} catch ( SQLException se ) {
myLogger . log (" sql " , " SQL - Fehler :
• " + se . toString () ) ;
} catch ( Exception e ) {
myLogger . log (
" sql " ,
KAPITEL 4. MOBILE SUPERX
61
" DB - Zugriff - Fehler : " + e .
• toString () ) ;
}
}
}
}
else
{
ergebnis . add ( null ) ;
// klappt noch nicht !
ergebnis . add (" Maximale Login - Versuche
• b e r s c h r i t t e n ") ;
ergebnis . add (" null ") ;
ergebnis . add ( noAdmin ) ;
}
} else {
ergebnis . add ( null ) ;
ergebnis . add (" - - nicht bekannt ") ;
ergebnis . add (" null ") ;
ergebnis . add ( noAdmin ) ;
try {
myQuery . execute ( prot_sql . toString () ,
• myConnection , myRecordset ) ;
} catch ( SQLException e1 ) {
myLogger . log (
" sql " ,
" SQL - Fehler : "
+ prot_sql . toString ()
+ "\ n "
+ e1 . toString () ) ;
}
}
return ergebnis ;
}
}
KAPITEL 4. MOBILE SUPERX
62
XSL-Stylesheet für die Anmeldung (Menue)
Bei gültiger Authentifizierung wird somit ein XML-Dokument mit folgender
Document Type Definition (DTD) erzeugt:
Listing 4.3: menue.dtd
<? xml version ="1.0" encoding =" UTF -8"? >
<! ELEMENT menue ( user , nachricht , userid , eintraege ) >
<! ELEMENT user (# PCDATA ) >
<! ELEMENT nachricht (# PCDATA ) >
<! ELEMENT userid (# PCDATA ) >
<! ELEMENT eintraege ( eintrag ) * >
<! ELEMENT eintrag ( zeile , id , tid , titel , parent ) >
<! ELEMENT zeile (# PCDATA ) >
<! ELEMENT id (# PCDATA ) >
<! ELEMENT tid (# PCDATA ) >
<! ELEMENT titel (# PCDATA ) >
<! ELEMENT parent (# PCDATA ) >
Ein Ausschnitt des XML-Dokuments, welches im Servlet erzeugt wurde,
könnte beispielsweise so aussehen:
Listing 4.4: menue.xml
< menue >
< user > christoph </ user >
< nachricht > Willkommen Christoph </ nachricht >
< userid >5 </ userid >
< eintraege >
< eintrag >
< zeile >1 </ zeile >
...
</ eintrag >
...
< eintrag >
< zeile >8 </ zeile >
<id >1111 </ id >
<tid >10000 </ tid >
< titel > Benutzer von SuperX </ titel >
< parent >2 </ parent >
</ eintrag >
...
</ eintraege >
</ menue >
KAPITEL 4. MOBILE SUPERX
63
Unser Menü setzt sich also aus der Menge aller Einträge zusammen. Um
das XML-Dokument nun in HTML zu transformieren verwendet man das
XSL-Stylesheet mobile menu.xsl. Danach kann es wie gewünscht im PDABrowser dargestellt werden. Nach der XML-Deklartion wird durch das Wurzelelement <xsl:stylesheet> die eingesetzte XSLT-Version sowie der XMLNamensraum definiert.
Listing 4.5: mobile menu.xsl
<? xml version ="1.0" encoding =" ISO -8859 -1"? >
< xsl : stylesheet version ="1.0" xmlns : xsl =" http :// www . w3 .
• org /1999/ XSL / Transform " >
Als Nächstes geben wir die Methode für die Ausgabe an. Laut XSLT-Spezifikation sind drei Ausgabemethoden definiert: xml, html und text. Wir wählen
html:
< xsl : output method =" html " indent =" yes " / >
Die erste Template beginnt und der XPath-Ausdruck “/“ verweist auf das
Wurzelelement des XML-Dokuments.
< xsl : template match ="/" >
Die Variable user wird für die aktuelle Template definiert, als Inhalt bekommt sie den Wert, der zwischen Anfangs-Tag <user> und Abschluß-Tag
</user> in unserer Struktur steht.
< xsl : variable name =" user " select =" menue / user "/ >
Ab hier werden auch HTML-Elemente in das Dokument eingefügt. Es beginnt
mit dem üblichen HTML-Head:
< html >
< head >
< meta http - equiv =" Content - Type " content =" text / html ;
• charset = windows -1252" / >
< title > Mobile SuperX </ title >
< link rel =" stylesheet " type =" text / css " href ="../ style /
• pda . css "/ >
</ head >
Das angebebene CSS (Cascading Style Sheet) auf der beigelegten CD zu finden. Es dient zur Festlegung der Link-Darstellungsform. Weiter geht es mit
dem Body. An dieser Stelle wird eine für das ganze Frontend gültige Navigationsleiste eingefügt. Sie beeinhaltet Buttons, um ein, beziehungsweise zwei
KAPITEL 4. MOBILE SUPERX
64
Sprünge in der History nach hinten zu gehen, die Logout-Funktion und eine
Statusleiste. Weitere Funktionen können später leicht hinzugefügt werden.
Nach der Anmeldung zeigt die Statusleiste hier die vom Servlet generierte
Nachricht an, also zum Beispiel “Willkommen Christoph!“.
< body bgcolor ="# C7E6FE " >
< table border ="1" width ="280" cellspacing ="0"
• bordercolor =" black " >
< tr bgcolor =" white " > < td > < strong > Mobile SuperX </ strong
• > </ td >
<td > & lt ;  & lt ;& lt ;  </ td >
<! - - < td >+   - </ td > - - >
<td > < a href ="../ servlet / M obil eSupe rxAb meld ung " title ="
• Abmelden " > logout </ a > </ td > </ tr >
< tr bgcolor =" white " >
< td colspan ="3" > < xsl : copy - of select =" menue / nachricht "
• / >! </ td >
</ tr >
</ table >
< br / >
Nun wird ein Formular erzeugt, welches dem Anwender in erster Linie die
Auswahl zwischen den einzelnen Bereichen (z.B. Kostenrechnung) ermöglicht.
Zunächst werden die Anwender-Kennung und die Transaktions-ID versteckt
eingefügt und dann erst die Template eintraege aufgerufen.
  G e w n s c h t e n Bereich a u s w h l e n :
< form action = ’ MobileSuperxMenue ’ method = ’ post ’ target = ’
• _self ’ >
< input type =" hidden " name =" user " >
< xsl : attribute name =" value " >
< xsl : value - of select =" $user " / >
</ xsl : attribute >
</ input >
< input type =" hidden " name =" tid " value ="" > </ input >
< xsl : call - template name =" eintraege " > </ xsl : call • template >
</ form >
</ body >
</ html >
</ xsl : template >
KAPITEL 4. MOBILE SUPERX
65
Wir wollen jetzt dem Anwender nur die Überschriften der Bereiche zur Auswahl anbieten. Im XML-Frontend wird an dieser Stelle der komplette Baum
angezeigt, was aber für Mobile SuperX viel zu unübersichtlich wäre. Die Template eintraege sucht den Eintrag (Wurzel), bei dem parent gleich “null“
ist, alle anderen sind Nachkommen von diesem. Haben wir den Eintrag gefunden, ruft man die Template suche kinder auf und übergibt dabei den
Parameter elter mit dem Wert von id.
< xsl : template name =" eintraege " >
< xsl : for - each select =" menue / eintraege / eintrag " >
< xsl : if test =" parent = ’ null ’" >
< xsl : call - template name =" suche_kinder " >
< xsl : with - param name =" elter " select =" id "/ >
< xsl : with - param name =" ebene " select ="1"/ >
</ xsl : call - template >
</ xsl : if >
</ xsl : for - each >
</ xsl : template >
Die Template suche kinder ermittelt nun die direkten Nachkommen der
Wurzel (= Eintrag “Abfragen“). Dafür wird wiederum jeder Eintrag in die
Hand genommen und geschaut, ob der Vorgänger (parent) gleich der ID
(Parameter elter) ist. Jeder passende Eintrag wird sortiert einer Liste mit
den Links zu den Untermenüs hinzugefügt.
< xsl : template name =" suche_kinder " >
< xsl : param name =" elter "/ >
< xsl : param name =" ebene "/ >
<ul >
< xsl : for - each select ="../ eintrag " >
< xsl : sort select =" titel "/ >
< xsl : variable name =" i " select =" parent "/ >
< xsl : if test =" $i = $elter " >
<li > < a target =" _self " > < xsl : attribute name =" href " >
• Mobi leSup erxMenue ? tid = < xsl : value - of select ="
• tid " / >& amp ; UserID = < xsl : value - of select ="/
• menue / userid " / >& amp ; auswahl = < xsl : value - of
• select =" id " / >& amp ; name = < xsl : value - of
• select =" titel " / > </ xsl : attribute >
< xsl : value - of select =" titel " / > </a >
</ li >
</ xsl : if >
</ xsl : for - each >
KAPITEL 4. MOBILE SUPERX
66
Abbildung 4.8: Das erste Menü von Mobile SuperX
<li > < a target =" _self " > < xsl : attribute name =" href " >../
• mobile / diagramme . html </ xsl : attribute > Diagramme </
• a > </ li >
</ ul >
</ xsl : template >
</ xsl : stylesheet >
Abbildung 4.8 zeigt das erste Menü mit der Auswahl der Bereiche (Anmerkung: die Bereiche “Statistik“ und “Diagramme“ werden in Kapitel 5 eingefügt und erklärt).
4.5.2
Untermenü
Bis jetzt kann der Anwender nur den gewünschten Bereich seiner Abfrage
auswählen. Man braucht jetzt also das Untermenü, welches die der Auswahl
untergeordneten Einträge liefert. Zum Beispiel ist für die Auswahl des Bereiches “Kostenrechnung“ ein Untermenüpunkt “Studierende (gewichtet)“. Da
es im XML-Frontend kein Untermenü gab, muss das Servlet dafür komplett
neu erstellt werden.
Servlet für das Untermenü
Zuerst werden wieder die benötigten Pakete importiert:
Listing 4.6: MobileSuperxMenue.java
package de . superx . servlet ;
// File : Mo bileSu perxMenue . java
KAPITEL 4. MOBILE SUPERX
import
import
import
import
import
import
import
import
import
import
import
import
import
67
javax . servlet .*;
javax . servlet . http .*;
java . security . MessageDigest ;
java . io .*;
java . text . DateFormat ;
java . util .*;
java . sql .*;
javax . xml . transform . TransformerFactory ;
javax . xml . transform . Transformer ;
javax . xml . transform . Source ;
javax . xml . transform . stream . StreamSource ;
javax . xml . transform . stream . StreamResult ;
de . superx . util . SqlStringUtils ;
Hier beginnt nun die Klasse MobileSuperxMenue, sie erbt die Eigenschaften
von HttpServlet und erweitert dieses:
public class Mo bileSu perxMenue extends HttpServlet
{
public static Logger my_logger ;
ResourceBundle rb = ResourceBundle . getBundle ("
• LocalStrings ") ;
public void init ( ServletConfig config ) throws
• ServletException
{
super . init ( config ) ;
my_logger = new Logger () ;
ServletUtils . init_logging ( config , my_logger ) ;
}
Die Methode doPost() definiert wiederum, wie das Servlet auf Anfragen zu
antworten hat. Dafür werden zahlreiche Variablen deklariert, so auch der
neue XML-String xml2 sowie die Hashtabellen eltern und bereiche:
public void doPost ( HttpServletRequest request ,
• H tt p S e rv l e tR e sponse response )
throws ServletException , IOException {
Obj ectInp utStre am inputFromApplet = null ;
O bje ct Ou tp ut St re am outputToApplet = null ;
String query = null ;
SuperX_el aSuperX_el = null ;
PrintWriter out = null ;
BufferedReader inTest = null ;
KAPITEL 4. MOBILE SUPERX
68
Vector rows = new Vector () ;
String xml2 = "";
Vector zeilenobjekt = new Vector () ;
Vector zobjekt = new Vector () ;
SuperX_el gesamt = new SuperX_el () ;
SuperX_el subquery = new SuperX_el () ;
SuperX_el sx_stylesheets = new SuperX_el () ;
SxSQL_Server aQuery = null ;
SxSQL_Server aSubQuery = null ;
SxSQL_Server MaskQuery = null ;
ConnectionPool Ma skConnectionpool = null ;
Connection MaskDbConnection = null ;
ConnectionPool poolConnection = null ;
Connection dbConnection = null ;
long callerId = IDGenerator . getInstance () . getID () ;
ConnectionPool su bqueryConnection = null ;
Connection s u b q u e r yDbConnection = null ;
Hashtable eltern = new Hashtable () ;
Hashtable bereiche = new Hashtable () ;
String tid = "";
String user ="";
String userid ="";
String db_driver ="";
String sqlErg ="";
String passwd ="";
Short adminUser = new Short (( short ) 0) ;
String login_name = " null ";
int n u mb e r Of S t yl e s heets =0;
Vector a u t h e n t i c a t ionVector = null ;
String msg_welcome = rb . getString (" superx . welcome ") ;
String msg_denied = rb . getString (" superx . denied ") ;
String msg_cookie = rb . getString (" superx . cookietext ") ;
HttpSession session = request . getSession ( true ) ;
String auswahl = "";
String name = "";
auswahl = ( String ) request . getParameter (" auswahl ") ;
name = ( String ) request . getParameter (" name ") ;
userid = ( String ) request . getParameter (" userid ") ;
Die aktuelle Session, die in MobileSuperXAnmeldung erstellt wurde, wird
eingelesen. Falls dies nicht möglich ist, entsteht eine Fehlermeldung und der
Anwender muss sich erneut anmelden.
KAPITEL 4. MOBILE SUPERX
69
/* Einlesen der aktuellen Session . Fehlermeldung
• wenn nicht moeglich */
try {
if ( session . getAttribute (" UserID ") != null )
{
userid = session . getAttribute (" UserID ") .
• toString () ;
if (! userid . equals (" false ") )
{
passwd = session . getAttribute (" password ") .
• toString () ;
my_logger . log (" conn " , " Getting Session :
• Userid "+ userid +" password : " +
• passwd ) ;
}
}
else
{
my_logger . log (" conn " , " Session kann nicht
• eingelesen werden . Diese Servlet - Engine
• ist nicht kompatibel ") ;
}
}
catch ( Exception e )
{
my_logger . log (" conn " , e . toString () ) ;
userid =" false ";
passwd ="";
}
Es wird jetzt begonnen, den XML-String aufzubauen, Wurzelelement ist wieder menue. In auswahl steht der gewählte Bereich (z.B. Kostenrechnung):
try
{
tid = ( String ) request . getParameter (" tid ") ;
xml2 += " < menue >";
xml2 += " < nachricht >"+ auswahl +" </ nachricht >";
xml2 += " < auswahl >"+ auswahl +" </ auswahl >";
KAPITEL 4. MOBILE SUPERX
70
Die SQL-Anfrage wird genauso wie im Servlet MobilSuperxAnmeldung gebildet:
java . util . Date date = new java . util . Date () ;
if ( db_driver . equals (" org . postgresql . Driver ") )
{
query = " select sp_user_themen ("+ userid .
• toString () +" , today () ,1) ; select distinct
• tid , name , maskeninfo_id , parent ,
• erlaeuterung from tmp_themenbaum ;";
}
else
{
if ( db_driver . equals (" com . informix . jdbc .
• IfxDriver ") )
{
query =" execute procedure sp_user_themen
• ("+ userid . toString () +" , today ,1) ;
• select distinct tid , name ,
• maskeninfo_id , parent , erlaeuterung
• from tmp_themenbaum ;";
}
else
{
query = " select tid , name , maskeninfo_id
• , parent , gueltig_seit , gueltig_bis
• from themenbaum order by name ;";
}
}
}
catch ( Exception e )
{
my_logger . log (" sql " , e . toString () ) ;
}
Die Datenbankverbindung für die aktuelle Abfrage wird aus dem Pool geholt:
try
{
aQuery = new SxSQL_Server ( my_logger ) ;
poolConnection = ConnectionPool . getInstance (
• my_logger ) ;
dbConnection = poolConnection . getConnection (
• callerId , this ) ;
KAPITEL 4. MOBILE SUPERX
71
db_driver = poolConnection . m_DriverClass ;
a u t h e n t i c a t i o n Vector = SqlStringUtils .
• authenticate ( aQuery , my_logger , dbConnection ,
• gesamt , userid , passwd ) ;
login_name =( String ) authenticationVector .
• elementAt (1) ;
passwd =( String ) authenticationVector . elementAt
• (2) ;
adminUser = ( Short ) authenticationVector .
• elementAt (3) ;
aQuery . executeQuery ( query , dbConnection , gesamt )
• ;
}
catch ( SQLException e )
{
my_logger . log (" sql " , e . toString () + " "+ e .
• getSQLState () ) ;
gesamt . setError_String ( e . getSQLState () ) ;
}
catch ( DB Se rv le tE xception de )
{
my_logger . log (" sql " , de . toString () ) ;
gesamt . setError_String ( de . toString () ) ;
}
catch ( Exception e )
{
my_logger . log (" sql " , e . toString () ) ;
gesamt . setError_String ( e . toString () ) ;
}
finally
{
if ( poolConnection != null && dbConnection
• != null )
{
my_logger . log (" conn " , " Verbindung
• zurueckgegeben ") ;
poolConnection . returnConnection ( callerId , this ) ;
}
else
{
my_logger . log (" conn " , " Fatal error ....")
• ;
}
KAPITEL 4. MOBILE SUPERX
72
}
poolConnection . returnConnection ( callerId , this ) ;
PrintWriter output = response . getWriter () ;
Es folgt nochmals eine Prüfung, ob es sich um einen korrekten Benutzernamen handelt, beziehungsweise ob er korrekt eingelesen worden ist:
if ( login_name . equals (" null ") )
{
xml2 += ServletUtils . Login_failure ( msg_denied ,
• msg_cookie + " " + rb . getString (" superx .
• logintext ") , rb . getString (" superx . login ") ,
• user ) ;
}
Ist bis hierhin kein Fehler aufgetreten, wird der XML-String erweitert:
else
{
try
{
/* Der XML - String xml2 wird aufgebaut */
xml2 += " < UserID >"+ userid +" </ UserID >";
xml2 += " < name >"+ name +" </ name >";
xml2 += " < eintraege >";
Auch dieses Mal werden alle Reihen der Ergebnistabelle (gesamt) einzeln
durchgegangen. Zusätzlich werden aber noch die beiden Hashtabellen mit
der ID und dem Parent der Abfrage gefüllt. Daraus ergeben sich dann zwei
Tabellen, momentan mit identischem Inhalt, die die ID als Schlüssel (key)
und Parent als Wert (value) haben.
int numberOfColumns = gesamt . getColumnCount () ;
rows = gesamt . getRows () ;
for ( int z = 0; z < rows . size () ; z ++)
{
zobjekt = ( Vector ) rows . elementAt ( z ) ;
String key = "";
String value = "";
key += zobjekt . elementAt (0) ;
value += zobjekt . elementAt (3) ;
eltern . put ( key , value ) ;
KAPITEL 4. MOBILE SUPERX
73
bereiche . put ( key , value ) ;
}
Die Einträge der Hashtabellen mit ‘Schlüssel gleich eins‘ werden gelöscht,
dies ist das Wurzelelement des Abfragebaumes. Von jeder Tabelle wird dann
noch ein Kopie angelegt:
bereiche . remove ("1") ;
eltern . remove ("1") ;
Hashtable eltern_copy = ( Hashtable ) eltern . clone
• () ;
Hashtable bereiche_copy = ( Hashtable ) bereiche .
• clone () ;
Die folgende While-Schleife läuft, solange es weitere Schlüssel in bereiche copy
gibt. Innerhalb der Schleife wird geprüft, ob der aktuelle Schlüssel auf den
Wert “1“ zeigt. Ist dies nicht der Fall, wird der Eintrag gelöscht. In der Hashtabelle stehen jetzt also nur noch direkte Nachfolger des Wurzelelements,
und das sind genau die gesuchten Bereiche.
Iterator i2 = bereiche_copy . keySet () . iterator () ;
while ( i2 . hasNext () )
{
String element2 = ( String ) i2 . next () ;
boolean result = bereiche . get (( String )
• element2 ) . equals ("1") ;
if ( result == false )
{
bereiche . remove ( element2 ) ;
}
}
In der nächsten While-Schleife wird nun jeder Abfrage aus unserer Liste der
übergeordnete Bereich zugeordnet. Ziel ist, dass in der Hashtabelle eltern
als Schlüssel alle IDs auftauchen und dazu als Wert die ID des passenden
Bereiches. Dies ist notwendig, da nicht alle Abfragen direkter Nachfolger der
Bereichsüberschrift sind (z.B. ‘Administration - Masken - Masken kopieren‘;
Masken ist hier keine Abfrage, sondern eine weitere Einteilung des Menüs)
Zuerst wird geprüft, ob der Wert zum aktuellen Schlüssel auch Schlüssel in
bereiche ist, wenn ja, ändert sich natürlich nichts mehr:
Iterator i = eltern_copy . keySet () . iterator () ;
while ( i . hasNext () )
{
KAPITEL 4. MOBILE SUPERX
74
String element = ( String ) i . next () ;
if ( bereiche . containsKey (( String ) eltern . get (
• element ) ) != true )
Ist dies nicht der Fall, schreibt man den Wert in den String x. Jetzt betrachtet
man x als ID und schreibt in den String x2 den dazu gehörenden Wert, dann
löscht man den aktuellen Eintrag aus der Tabelle. Stattdessen wird dieser als
Schlüssel mit dem neuen Wert x2 eingetragen.
{
String x = "";
x += ( String ) eltern . get ( element ) ;
String x2 = "";
x2 += ( String ) eltern . get ( x ) ;
eltern . remove ( element ) ;
eltern . put ( element , x2 ) ;
In der Hashtabelle eltern steht jetzt die ID und die des Vorvorgängers (falls
vorhanden). Danach führt man die beschriebene Prozedur nochmals durch,
damit man auch den Vorgänger des Vorvorgängers findet.
if ( bereiche . containsKey (( String ) eltern .
• get ( element ) ) != true )
{
x = "";
x += ( String ) eltern . get ( element ) ;
x2 = "";
x2 += ( String ) eltern . get ( x ) ;
eltern . remove ( element ) ;
eltern . put ( element , x2 ) ;
}
}
}
Falls nötig, kann man obiges noch einmal wiederholen. Bei den bisherigen
Modulen reichen die beiden Durchläufe allerdings aus. Wiederum wird jetzt
das XML-Dokument zusammengebaut, allerdings kommt im Vergleich zum
MobileSuperxAnmeldung-Servlet noch die Wurzel (in ihr steht der zur Abfrage gehörende Bereich) hinzu, welche aus der Hashtabelle eltern entnommen
wird:
for ( int zeile = 0; zeile < rows . size () ; zeile
• ++)
{
KAPITEL 4. MOBILE SUPERX
75
zeilenobjekt = ( Vector ) rows . elementAt ( zeile
• );
String id = "";
id += zeilenobjekt . elementAt (0) ;
xml2 += " < eintrag > < zeile >"
+ ( zeile + 1)
+ " </ zeile > < id >"
+ zeilenobjekt . elementAt (0)
+ " </ id > < tid >"
+ zeilenobjekt . elementAt (2)
+ " </ tid > < titel >"
+ zeilenobjekt . elementAt (1)
+ " </ titel > < parent >"
+ zeilenobjekt . elementAt (3)
+ " </ parent > < wurzel >"
+ ( String ) eltern . get ( id )
+ " </ wurzel > </ eintrag >";
}
xml2 += " </ eintraege >";
poolConnection . returnConnection ( callerId , this ) ;
}
catch ( SQLException e )
{
my_logger . log (" sql " , e . toString () ) ;
gesamt . setError_String ( e . getSQLState () ) ;
}
}
Das XML-Dokument wird beendet und mitgeloggt:
xml2 += " </ menue >";
my_logger . log (" sql " , " xml - Stream : " + xml2 ) ;
PrintWriter output = response . getWriter () ;
Das zugehörige XSL-Stylesheet wird festgelegt und die Transformation kann
beginnen:
try
{
String Stil ;
response . setContentType (" text / html ; charset = ISO
• -8859 -1") ;
Stil = " mobile / mobile_menu2 . xsl ";
KAPITEL 4. MOBILE SUPERX
76
javax . xml . transform . TransformerFactory tFactory
• =
javax . xml . transform . TransformerFactory .
• newInstance () ;
javax . xml . transform . Transformer transformer =
tFactory . newTransformer ( new javax . xml . transform .
• stream . StreamSource (
" file :///"+ getServletConfig () .
• get ServletContext () . getRealPath ( Stil ) ) )
• ;
StringReader s1 = new StringReader (" <? xml
• version = ’1.0 ’ encoding = ’ ISO -8859 -1 ’? >"+
• xml2 ) ;
transformer . transform (
new javax . xml . transform . stream . StreamSource (
• s1 ) ,
new javax . xml . transform . stream . StreamResult (
• output ) ) ;
}
catch ( Exception e )
{
my_logger . log (" sql " , " An error occurred
• processing your operation ..."
+ e . toString () ) ;
response . setContentType (" text / html ; charset = ISO
• -8859 -1") ;
output . println ( de . superx . servlet . ServletUtils .
• xml_fehler ( e . toString () , xml2 ) ) ;
}
}
GET-Requests sollen wieder genauso behandelt werden wie POST-Requests:
public void doGet ( HttpServletRequest request ,
• H tt p S e rv l e tR e sponse response )
throws ServletException , IOException {
doPost ( request , response ) ;
}
public String getServletInfo ()
{
KAPITEL 4. MOBILE SUPERX
77
return " <i > MobileSuperxMenue </ i >";
}
}
XSL-Stylesheet für das Untermenü
Das XSL-Stylesheet beginnt genauso wie das vorherige auch, dazu kommen
einige globale Variablen, die für alle Templates gelten:
Listing 4.7: mobile menu2.xsl
<? xml version ="1.0" encoding =" ISO -8859 -1"? >
< xsl : stylesheet version ="1.0" xmlns : xsl =" http :// www . w3 .
• org /1999/ XSL / Transform " >
< xsl : output method =" html " indent =" yes " / >
< xsl : variable name =" auswahl " select =" menue / auswahl " / >
< xsl : variable name =" userid " select =" menue / userid " / >
< xsl : variable name =" name " select ="/ menue / name " / >
< xsl : template match ="/" >
< xsl : variable name =" user "
select = " menue / user "/ >
Der HTML-Teil beginnt auch wie üblich. Mit Hilfe von JavaScript wird der
Rückwärtsbutton aktiviert. In der Statusleiste steht jetzt der Name des Bereiches.
< html >
< head >
< meta http - equiv =" Content - Type " content =" text / html ;
• charset = windows -1252" / >
< title > Mobile SuperX </ title >
< link rel =" stylesheet " type =" text / css " href ="../ style /
• pda . css "/ >
</ head >
< body bgcolor ="# C7E6FE " >
< table border ="1" width ="280" cellspacing ="0"
• bordercolor =" black " >
< tr bgcolor =" white " width ="280" >
<td > < strong > Mobile SuperX </ strong > </ td >
<td >  < a href =" javascript : history . go ( -1) " >& lt ; </
• a >  & lt ;& lt ;  </ td >
KAPITEL 4. MOBILE SUPERX
78
<! - - < td >+   - </ td > - - >
<td > < a href ="../ servlet / M obile Supe rxAb meldu ng " title
• =" Abmelden " > logout </ a > </ td >
</ tr >
< tr bgcolor =" white " width ="280" >
< td colspan ="3" > < xsl : value - of select =" $name " / > </ td >
</ tr >
</ table >
Die Schriftgrösse wird heruntergesetzt, um das Menü für PDAs übersichtlich zu gestalten. Das Formular besteht jetzt aus den Listeneinträgen der
Abfragen, welche dem Bereich zugeordnet sind (z.B. Benutzer von SuperX).
Generiert werden die Links über die Template eintraege.
< font size =" -1" >
< form action = ’ MobileSuperxMaske ’ method = ’ post ’ target = ’
• _self ’ >
< input type =" hidden " name =" user " >
< xsl : attribute name =" value " > < xsl : value - of select ="
• $user " / >
</ xsl : attribute >
</ input >
< input type =" hidden " name =" tid " value ="" >
</ input >
<ul >
< xsl : call - template name =" eintraege " > </ xsl : call • template >
</ ul >
</ form >
</ font >
</ body >
</ html >
</ xsl : template >
Die Einträge und die zugehörigen Kinder werden durch die Template
eintraege genauso gesucht wie bereits in mobile menu.xsl:
< xsl : template name =" eintraege " >
< xsl : for - each select =" menue / eintraege / eintrag " >
< xsl : if test =" parent = ’ null ’" >
KAPITEL 4. MOBILE SUPERX
79
< xsl : call - template name =" suche_kinder " >
< xsl : with - param name =" elter " select =" id "/ >
< xsl : with - param name =" ebene " select ="1"/ >
</ xsl : call - template >
</ xsl : if >
</ xsl : for - each >
</ xsl : template >
Auch das Template suche kinder funktioniert auf dieselbe Art und Weise.
< xsl : template name =" suche_kinder " >
< xsl : param name =" elter "/ >
< xsl : param name =" ebene "/ >
< xsl : for - each select ="../ eintrag " >
< xsl : sort select =" titel "/ >
< xsl : variable name =" i " select =" parent "/ >
< xsl : if test =" $i = $elter " >
< xsl : if test =" tid = ’ null ’" >
< xsl : if test =" wurzel = $auswahl " >
< xsl : value - of select =" titel " / > 
</ xsl : if >
</ xsl : if >
< xsl : if test =" tid != ’ null ’" >
< xsl : if test =" wurzel = $auswahl " >
<li > < a target =" _self " > < xsl : attribute name =" href
• " > SuperXmlMaske ? tid = < xsl : value - of select ="
• tid " / >& amp ; UserID = < xsl : value - of select ="
• userid " / > </ xsl : attribute >
< xsl : value - of select =" titel " / > </a >
</ li >
</ xsl : if >
</ xsl : if >
Allerdings werden nun auch Kinder der Kinder gesucht, also eine Ebene tiefer.
Dafür ruft man die Template suche kinder rekursiv auf:
< xsl : call - template name =" suche_kinder " >
< xsl : with - param name =" elter " select =" id "/ >
< xsl : with - param name =" ebene " select =" $ebene +1"/ >
</ xsl : call - template >
</ xsl : if >
</ xsl : for - each >
</ xsl : template >
KAPITEL 4. MOBILE SUPERX
Abbildung 4.9: Das Untermenü für die
Kostenrechnung
80
Abbildung 4.10: Das Untermenü für
die Administration
</ xsl : stylesheet >
Die Abbildungen 4.9 und 4.10 zeigen die Untermenüs für die Kostenrechnung
und die Administration, bei letzterem sieht man die weitere Unterteilung des
Menüs in ‘Benutzer‘und ‘Masken Felder‘.
4.5.3
Maske
In der Maske kann man die im Untermenü ausgewählte Anfragen weiter
spezifizieren. Dies geschieht mit Hilfe von Pulldown-Menüs.
Servlet für die Maske
Das Servlet SuperXmlMaske des XML-Frontends muss nur sehr geringfügig
geändert werden. Daher möchte ich hier auch nur die nötigen Veränderungen
darstellen. Klar ist, dass man die Klasse umbenennen muss, sie heißt jetzt
MobileSuperxMaske:
public class Mo bileSu perxMaske extends HttpServlet {
Wie das neue XSL-Stylesheet heißt, wird ebenfalls angegeben:
Stil = " mobile / mobile_maske . xsl ";
Wenn die User-Agent-Erkennung richtig funktionieren würde, könnte man
sogar das “alte“ Servlet komplett beibehalten. Man müsste einfach eine weitere Überprüfung einbauen, ob ein bestimmter String (z.B. PDA, NetFront
KAPITEL 4. MOBILE SUPERX
81
oder Palm) in dem HTTP-Header enthalten ist und dann dementsprechend
den Stil festlegen. Leider geben viele PDA-Browser aber nur den Standard
(Mozilla 4.0) und nicht zum Beispiel das PDA-Betriebssystem an. In diesem
Zusammenhang wäre auch denkbar, dass man Mobile SuperX für verschiedene PDAs und Browser optimiert.
Ansonsten arbeitet das Servlet genauso wie die vorherigen, die Datenbankverbindung wird hergestellt, die SQL-Anfrage angewendet und aus dem
Ergebnis ein XML-Dokument gebaut, welches dann wiederum transformiert
wird.
XSL-Stylesheet für die Maske
Auch am Stylesheet sind nur kleinere Veränderungen notwendig. Zu Beginn
bleibt alles beim Alten:
Listing 4.8: mobiel maske.xsl
<? xml version ="1.0" encoding =" ISO -8859 -1"? >
< xsl : stylesheet version ="1.0" xmlns : xsl =" http :// www . w3 .
• org /1999/ XSL / Transform " >
< xsl : template match ="/" >
< html >
< head >
< meta http - equiv =" Content - Type " content =" text / html ;
• charset = windows -1252"/ >
< title > Mobile SuperX </ title >
< link rel =" stylesheet " type =" text / css " href ="../ style
• / pda . css "/ >
</ head >
< body bgcolor ="# C7E6FE " >
Beide Rückwärtsbutton werden jetzt in der Navigationsleiste aktiviert. In
der Statuszeile steht der Name der gewählten Maske, wobei dieser nach 31
Zeichen abgeschnitten und durch “...“ abgeschlossen wird.
< table border ="1" width ="280" cellspacing ="0"
• bordercolor =" black " >
< tr bgcolor =" white " >
<td > < strong > Mobile SuperX </ strong > </ td >
<td >  < a href =" javascript : history . go ( -1) " >& lt
• ; </a >   < a href =" javascript : history .
• go ( -2) " >& lt ;& lt ; </a >  </ td >
KAPITEL 4. MOBILE SUPERX
82
<! - - < td >+   - </ td > - - >
<td > < a href ="../ servlet / M obil eSupe rxAb meld ung "
• title =" Abmelden " > logout </ a > </ td >
</ tr >
< tr bgcolor =" white " >
< td colspan ="3" >
< xsl : if test =" string - length ( maske / felder / feld /
• maskenname ) & gt ;31" >
< xsl : value - of select =" substring ( maske / felder /
• feld / maskenname ,0 ,31) " / >...
</ xsl : if >
< xsl : if test =" string - length ( maske / felder / feld /
• maskenname ) & lt ;=31" >
< xsl : value - of select =" maske / felder / feld /
• maskenname " / >
</ xsl : if >
</ td >
</ tr >
</ table >
Falls Nachrichten aus dem Servlet vorliegen, werden diese nun angezeigt:
< xsl : if test ="/ maske / nachricht != ’ ’" >
<p > < xsl : copy - of select ="/ maske / nachricht " / > </p >
</ xsl : if >
Das Formular der Maske wird per HTTP-POST an MobileSuperxTabelle
gesendet. Inhalt ist die UserID:
< form name =" maske " action =" MobileSuperxTabelle " method ="
• post " >
< input type =" hidden " name =" UserID " >
< xsl : attribute name =" value " > < xsl : value - of select
• ="/ maske / UserID "/ > </ xsl : attribute >
</ input >
Eine Liste wird gebildet, in der die Selektionen der Maske als Pull-DownMenü angeboten werden. Für jedes Feld wird die Template feld aufgerufen.
Des Weiteren werden der Submit- und Reset-Button erstellt.
<ul >
< font size =" -1" >
< xsl : for - each select =" maske / felder " >
< input type =" hidden " name =" tid " >
KAPITEL 4. MOBILE SUPERX
83
< xsl : attribute name =" value " >
< xsl : value - of select ="../../ maske / @tid "/ >
</ xsl : attribute >
</ input >
< xsl : for - each select =" feld " >
<p > < xsl : call - template name =" feld " > </ xsl : call • template > </p >
</ xsl : for - each >
<p > < input type =" submit " value =" Abschicken
• "/ > 
< input type =" reset " value =" reset " / > </p >
</ xsl : for - each >
</ font >
</ ul >
</ form >
</ body >
</ html >
</ xsl : template >
Die Template inputfeld wird aufgerufen:
< xsl : template name =" feld " >
< xsl : call - template name =" inputfeld "/ >
</ xsl : template >
An dieser Stelle fügt man der oben erstellten Liste die Pull-Down-Menüs als
Listenpunkte hinzu:
< xsl : template name =" inputfeld " >
< xsl : if test =" obligatorisch = ’1 ’" >
<b > < li > < xsl : value - of select =" name "/ > </ li > </b >
</ xsl : if >
< xsl : if test =" obligatorisch = ’0 ’" >
<li > < xsl : value - of select =" name "/ > </ li >
</ xsl : if >
Der folgende Abschnitt ist unverändert aus dem XML-Frontend übernommen. Aus dem XML-Dokument wird für jedes Pull-Down-Menü die Liste der
Einträge erzeugt.
< xsl : choose >
< xsl : when test =" art = ’0 ’" >
< xsl : if test =" zeilenanzahl = ’1 ’" >
KAPITEL 4. MOBILE SUPERX
84
< input type =" text " >
< xsl : attribute name =" NAME " >
< xsl : value - of select =" name "/ >
</ xsl : attribute >
< xsl : attribute name =" id " >
< xsl : value - of select =" name "/ >
</ xsl : attribute >
< xsl : attribute name =" MAXLENGTH " >
< xsl : value - of select =" laenge "/ >
</ xsl : attribute >
< xsl : attribute name =" VALUE " >
< xsl : value - of select =" defaultwert / sqlerg /
• row / col0 "/ >
</ xsl : attribute >
< xsl : attribute name =" size " >
< xsl : value - of select =" feldbreite "/ >
</ xsl : attribute >
</ input >
</ xsl : if >
< xsl : if test =" zeilenanzahl != ’1 ’" >
< textarea WRAP =" on " >
< xsl : attribute name =" cols " >
< xsl : value - of select =" feldbreite "/ >
</ xsl : attribute >
< xsl : attribute name =" rows " >
< xsl : value - of select =" zeilenanzahl "/ >
</ xsl : attribute >
< xsl : attribute name =" NAME " >
< xsl : value - of select =" name "/ >
</ xsl : attribute >
< xsl : value - of select =" defaultwert / sqlerg / row
• / col0 "/ >
</ textarea >
</ xsl : if >
</ xsl : when >
< xsl : when test =" art = ’1 ’" >
< SELECT >
< xsl : attribute name =" NAME " >
< xsl : value - of select =" name "/ >
</ xsl : attribute >
< OPTION / >
< xsl : for - each select =" relation / sqlerg / row " >
KAPITEL 4. MOBILE SUPERX
85
< OPTION >
< xsl : attribute name =" value " >
< xsl : value - of select =" col0 "/ >
</ xsl : attribute >
< xsl : if test ="../../../ defaultwert / sqlerg /
• row / col0 = col0 " >
< xsl : attribute name =" selected " >
true
</ xsl : attribute >
</ xsl : if >
< xsl : value - of select =" col1 "/ >
</ OPTION >
</ xsl : for - each >
</ SELECT >
</ xsl : when >
< xsl : when test =" art = ’2 ’" >
< SELECT >
< xsl : attribute name =" NAME " >
< xsl : value - of select =" name "/ >
</ xsl : attribute >
< OPTION / >
< xsl : for - each select =" relation / sqlerg / row " >
< OPTION >
< xsl : attribute name =" value " >
< xsl : value - of select =" col0 "/ >
</ xsl : attribute >
< xsl : if test ="../../../ defaultwert / sqlerg /
• row / col1 = col1 " >
< xsl : attribute name =" selected " >
true
</ xsl : attribute >
</ xsl : if >
< xsl : value - of select =" col1 "/ >
</ OPTION >
</ xsl : for - each >
</ SELECT >
</ xsl : when >
< xsl : when test =" art = ’3 ’" >
< input type =" file " >
< xsl : attribute name =" NAME " >
< xsl : value - of select =" name "/ >
</ xsl : attribute >
< xsl : attribute name =" size " >
KAPITEL 4. MOBILE SUPERX
< xsl : value - of select =" feldbreite "/ >
</ xsl : attribute >
</ input >
</ xsl : when >
< xsl : when test =" art = ’4 ’" >
< xsl : call - template name =" treeview " >
</ xsl : call - template >
< input type =" hidden " name =" Organigramm - Stand " >
< xsl : attribute name =" value " >
< xsl : value - of select ="/ maske / @datum "/ >
</ xsl : attribute >
</ input >
< input type =" hidden " name =" erlaubt " value ="1"/ >
</ xsl : when >
< xsl : when test =" art = ’6 ’" >
< xsl : call - template name =" treeview " >
</ xsl : call - template >
< input type =" hidden " name =" Organigramm - Stand " >
< xsl : attribute name =" value " >
< xsl : value - of select ="/ maske / @datum "/ >
</ xsl : attribute >
</ input > < input type =" hidden " name =" erlaubt " value
• ="1"/ >
</ xsl : when >
< xsl : when test =" art = ’7 ’" >
< xsl : call - template name =" treeview " >
</ xsl : call - template >
< input type =" hidden " name =" Organigramm - Stand " >
< xsl : attribute name =" value " >
< xsl : value - of select ="/ maske / @datum "/ >
</ xsl : attribute >
</ input >
< input type =" hidden " name =" erlaubt " value ="1"/ >
</ xsl : when >
< xsl : when test =" art = ’9 ’" >
< xsl : call - template name =" treeview " >
</ xsl : call - template >
</ xsl : when >
< xsl : when test =" art = ’10 ’" >
< input type =" checkbox " value =" true " >
< xsl : attribute name =" NAME " >
< xsl : value - of select =" name "/ >
</ xsl : attribute >
86
KAPITEL 4. MOBILE SUPERX
87
< xsl : attribute name =" checked " >
< xsl : value - of select =" defaultwert / sqlerg /
• row / col0 "/ >
</ xsl : attribute >
</ input >
</ xsl : when >
< xsl : when test =" art = ’11 ’" >
< xsl : if test =" zeilenanzahl = ’1 ’" >
< input type =" password " >
< xsl : attribute name =" NAME " >
< xsl : value - of select =" name "/ >
</ xsl : attribute >
< xsl : attribute name =" id " >
< xsl : value - of select =" name "/ >
</ xsl : attribute >
< xsl : attribute name =" MAXLENGTH " >
< xsl : value - of select =" laenge "/ >
</ xsl : attribute >
< xsl : attribute name =" VALUE " >
< xsl : value - of select =" defaultwert / sqlerg /
• row / col0 "/ >
</ xsl : attribute >
< xsl : attribute name =" size " >
< xsl : value - of select =" feldbreite "/ >
</ xsl : attribute >
</ input >
</ xsl : if >
</ xsl : when >
< xsl : otherwise > Unbekanntes Feld </ xsl : otherwise >
</ xsl : choose >
</ xsl : template >
< xsl : template name =" treeview " >
<! - - Das Treeview - Control geht davon aus , dass im
• sqlerg die Felder wie folgt belegt sind :
col0 enth ? lt den Volltext des Eintrags ,
col1 die nr bzw . key_apnr beim Organigramm
col2 den parent - Knoten
-->
< select >
< xsl : attribute name =" name " >
< xsl : value - of select =" name "/ >
KAPITEL 4. MOBILE SUPERX
88
</ xsl : attribute >
< option > </ option >
< xsl : variable name =" t_root "/ >
< xsl : for - each select =" relation / sqlerg / row " >
< xsl : if test ="(( col2 = ’ null ’) or ( col2 = ’ ’) ) " >
<! - - Zuerst wird root eingef ? gt , und dann alle
• Kinder von Root -->
< OPTION >
< xsl : attribute name =" value " >
< xsl : value - of select =" col1 "/ >
</ xsl : attribute >
< xsl : if test ="../../../ defaultwert / sqlerg /
• row / col1 = col1 " >
< xsl : attribute name =" selected " >
true
</ xsl : attribute >
</ xsl : if >
< xsl : value - of select =" col0 "/ >
</ OPTION >
< xsl : call - template name =" suche_kinder " >
< xsl : with - param name =" elter " select =" col1 "/ >
< xsl : with - param name =" ausgewaehlt " select
• ="../../../ defaultwert / sqlerg / row / col1 "/ >
< xsl : with - param name =" ebene " select ="0"/ >
</ xsl : call - template >
</ xsl : if >
</ xsl : for - each >
</ select >
</ xsl : template >
< xsl : template name =" suche_kinder " >
< xsl : param name =" elter "/ >
< xsl : param name =" ausgewaehlt "/ >
< xsl : param name =" ebene "/ >
< xsl : for - each select ="../ row " >
< xsl : variable name =" i " select =" col2 "/ >
KAPITEL 4. MOBILE SUPERX
89
< xsl : if test =" $i = $elter " >
< OPTION >
< xsl : attribute name =" value " >
< xsl : value - of select =" col1 "/ >
</ xsl : attribute >
< xsl : if test =" $ausgewaehlt = col1 " >
< xsl : attribute name =" selected " >
true
</ xsl : attribute >
</ xsl : if >
< xsl : call - template name =" levels " >
< xsl : with - param name =" ebene " select =" $ebene "/ >
</ xsl : call - template >
< xsl : value - of select =" col0 "/ >
</ OPTION >
< xsl : call - template name =" suche_kinder " >
< xsl : with - param name =" elter " select =" col1 "/ >
< xsl : with - param name =" ausgewaehlt " select ="
• $ausgewaehlt "/ >
< xsl : with - param name =" ebene " select =" $ebene
• +1"/ >
</ xsl : call - template >
</ xsl : if >
</ xsl : for - each >
</ xsl : template >
</ xsl : stylesheet >
Die Abbildungen 4.11 und 4.12 zeigen die Maske am Beispiel der Abfrage
“Benutzer von SuperX“.
4.5.4
Tabelle
In der Tabelle wird nun (endlich) das fertige Ergebnis unserer Abfrage angezeigt.
Servlet für die Tabelle
Wie schon bei der Maske sind die Änderungen am Servlet minimal. Die Klasse
muss umbenannt und das zugehörige XSL-Stylesheet wie immer als String
angeben werden:
KAPITEL 4. MOBILE SUPERX
Abbildung 4.11: In der Maske kann die
Anfrage spezifiziert werden.
90
Abbildung 4.12: Mobile Maske mit
geöffnetem Pull-Down-Menü
public class M ob i l eS u p erxTabelle extends HttpServlet {
mainStylesheet = " mobile / mobile_tabelle . xsl ";
Die DTD des entstandenen XML-Dokumentes soll hier ausschnittsweise angegeben werden. Dabei wird auf Attribute verzichtet, da diese im Stylesheet
mobile tabelle.xsl keine Rolle spielen.
Listing 4.9: tabelle.dtd
<? xml version ="1.0" encoding =" UTF -8"? >
<! ELEMENT sqlerg ( headers , row *) >
<! ELEMENT headers ( header ) + >
<! ELEMENT header ( wert ) >
<! ELEMENT wert (# PCDATA ) >
<! ELEMENT row ( col ) * >
<! ELEMENT col ( id , f_name , wert ) >
<! ELEMENT id (# PCDATA ) >
<! ELEMENT f_name (# PCDATA ) >
XSL-Stylesheet für die Tabelle
In dem Stylesheet für die Tabelle wird angegeben, wie die Ergebnis-Tabelle
aufgearbeitet werden soll. Das SQL-Ergebnis besteht aus den Headern (SpaltenÜberschriften) und den einzelnen Reihen. Die erste Template wird begonnen:
KAPITEL 4. MOBILE SUPERX
91
Listing 4.10: mobile tabelle.xsl
<? xml version ="1.0" encoding =" ISO -8859 -1"? >
< xsl : stylesheet version ="1.0" xmlns : xsl =" http :// www . w3 .
• org /1999/ XSL / Transform " >
< xml : output method =" html " / >
< xsl : template match ="/" >
Im Head des HTML-Teils werden zwei JavaScript-Funktionen definiert. Sie
dienen zum Ein- und Ausblenden von Spalten der Ergebnis-Tabelle, dies soll
die Übersicht verbessern. Leider unterstützen die getesteten PDA-Browser
diese JavaScript-Funktion momentan nicht. Trotzdem sollen sie im Code belassen werden, in der Hoffnung, dass zukünftige Browser mit einer besseren
JavaScript-Unterstützung aufwarten. In Desktop-Browsern gibt es keine Probleme mit den Funktionen, siehe dazu die Abbildungen 4.15 und 4.16.
< html >
< head >
< meta http - equiv =" Content - Type " content =" text / html ;
• charset = windows -1252" / >
< title > Mobile SuperX </ title >
< link rel =" stylesheet " type =" text / css " href ="../ style /
• pda . css " > </ link >
< script language =" JavaScript " >
function ausblenden ( colIndex ) {
var tabelle = document . all ? document . all . Tab :
document . getElementById ( ’ Tab ’) ;
for ( var r = 0; r & lt ; tabelle . rows . length ; r ++)
tabelle . rows [ r ]. cells [ colIndex ]. style . display = ’
• none ’;
}
function einblenden ( colIndex ) {
var table = document . all ? document . all . Tab :
document . getElementById ( ’ Tab ’) ;
for ( var r = 0; r & lt ; table . rows . length ; r ++)
table . rows [ r ]. cells [ colIndex ]. style . display = ’ ’;
}
</ script >
</ head >
KAPITEL 4. MOBILE SUPERX
92
In der Statusleiste wird der Maskenname diesmal bereits nach 18 Zeichen
abgeschnitten, da hier zusätzlich das Datum mit dem Stand der Daten in die
Tabelle eingefügt wird. Das Datum findet man in ergebnis/tabelle/stand.
Denkbar wäre hier auch, den abgeschnittenen Name der Maske in einem
JavaScript-Alert-Fenster vollständig anzuzeigen.
< body bgcolor ="# C7E6FE " > < form action =" SuperXmlTabelle "
• method =" post " target =" _self " >
< table border ="1" width ="280" cellspacing ="0"
• bordercolor =" black " >
< tr bgcolor =" white " > < td > < strong > Mobile SuperX </ strong > </
• td >
<td >  < a href =" javascript : history . go ( -1) " >& lt ; </a
• >   < a href =" javascript : history . go ( -2) " >&
• lt ;& lt ; </a >  </ td >
<td > < a href ="../ servlet / SuperXmlAbmeldung " title ="
• Abmelden " >  logout </ a > </ td > </ tr >
< tr bgcolor =" white " >
< td colspan ="3" >
< xsl : if test =" string - length ( ergebnis / tabelle /
• maskenname ) & gt ;18" >
< xsl : value - of select =" substring ( ergebnis /
• tabelle / maskenname ,0 ,18) " / >...
</ xsl : if >
< xsl : if test =" string - length ( ergebnis / tabelle /
• maskenname ) & lt ;=18" >
< xsl : value - of select =" ergebnis / tabelle /
• maskenname " / >
</ xsl : if >
  < xsl : value - of select =" ergebnis / tabelle /
• stand " / >
</ td >
</ tr >
</ table >
< br / >
Falls bei der Erstellung der Ergebnis-Tabelle im Servlet ein Fehler aufgetreten
ist, wird dieser nun angezeigt:
< xsl : if test ="/ ergebnis / nachricht != ’ ’" > <p >
< xsl : copy - of select ="/ ergebnis / nachricht " / > </p >
KAPITEL 4. MOBILE SUPERX
93
</ xsl : if >
< xsl : for - each select =" ergebnis / felder / msgs / msg " >
< xsl : if test =" wert != ’ ’" >
<p class =" errmsg " > < xsl : value - of select =" wert " / > </
• p>
</ xsl : if >
</ xsl : for - each >
< xsl : for - each select =" ergebnis / tabelle " >
< xsl : if test =" errmsg != ’ ’" >
<p class =" errmsg " > < xsl : copy - of select =" errmsg "
• / > </p >
</ xsl : if >
In ein HTML-Formular werden die oben beschriebenen JavaScript-Funktionen
zum Ein- und Ausblenden von Spalten eingebettet. Die Spalten werden von
links nach rechts mit aufsteigenden Zahlen belegt, beginnend bei der Eins.
In einem Pull-Down-Menü kann die gewünschte Spalte ausgewählt werden
und über die Buttons aus- beziehungsweise wieder eingeblendet werden:
< form >
< font size =" -1" > Spalte : </ font >
< select NAME =" colIndex " >
< script >
for ( var i = 1; i & lt ; 10; i ++)
document . write ( ’ < option value =" ’ + i + ’" > ’ + i + ’ </
• option > ’) ;
</ script >
</ select >
< input type =" button " value =" ausblenden "
onclick =" ausblenden ( this . form . colIndex .
• selectedIndex ) ;"/ >
< input type =" button " value =" einblenden "
onclick =" einblenden ( this . form . colIndex .
• selectedIndex ) ;"/ >
</ form >
Ab hier beginnt die Ergebnis-Tabelle, sie hat die ID Tab. Zunächst werden
die Überschriften der Spalten gebildet:
< table border ="1" ID =" Tab " cellspacing ="0"
• bordercolor =" black " >
<tr >
KAPITEL 4. MOBILE SUPERX
94
< xsl : for - each select =" sqlerg / headers / header " >
< td ID =" tab " bgcolor =" blue " >
< font size =" -2" color =" black " >
<b > < xsl : copy - of select =" wert " / > </b >
</ font >
</ td >
</ xsl : for - each >
</ tr >
Das Ergebnis der SQL-Abfrage wird nun Reihe für Reihe durchgegangen.
Um die Lesbarkeit zu verbessern, wird die Hintergrundfarbe nach jeder Reihe
gewechselt.
< xsl : for - each select =" sqlerg / row " >
<tr >
< xsl : attribute name =" bgcolor " >
< xsl : choose >
< xsl : when test =" position () mod 2" >
< xsl : text > white </ xsl : text >
</ xsl : when >
< xsl : otherwise >
< xsl : text ># C7E6FE </ xsl : text >
</ xsl : otherwise >
</ xsl : choose >
</ xsl : attribute >
In jeder einzelnen Reihe wird eine Spalte (also ein Feld) nach der anderen
abgearbeitet und mit dem entsprechenden Wert gefüllt:
< xsl : for - each select =" col " >
< td ID =" tab " >
< font size =" -2" > < xsl : value - of select =" wert " / > </
• font >
</ td >
</ xsl : for - each >
</ tr >
</ xsl : for - each >
</ table >
Weitere Nachrichten, falls vorhanden, und die Anzahl der Reihen werden am
Schluss noch aufgeführt, bevor das Stylesheet letztendlich geschlossen wird:
< font size =" -2" >
<p >
< xsl : value - of select =" sqlerg / msg " / > < br / >
KAPITEL 4. MOBILE SUPERX
Abbildung 4.13: Kleine Tabellen werden von Mobile SuperX übersichtlich
dargestellt.
95
Abbildung 4.14: Mit Hilfe der Buttons
kann man zur Auswahl zurückspringen.
< xsl : for - each select =" felder / msgs / msg " >
< xsl : value - of select =" wert " / > < br / >
</ xsl : for - each >
</p >
</ font >
</ xsl : for - each >
</ form >
</ body >
</ html >
</ xsl : template >
</ xsl : stylesheet >
Abbildung 4.13 zeigt, dass kleine Ergebnis-Tabellen in Mobile SuperX gut
darstellbar sind. Für Abbildung 4.14 gilt dies ebenfalls, hier wird der Titel in
der Statusleiste abgschnitten. Die Abbildungen 4.15 und 4.16 zeigen Mobile
SuperX mit JavaScript-Funktion im Internet Explorer auf einem gewöhnlichen PC.
KAPITEL 4. MOBILE SUPERX
Abbildung 4.15: Man hat die Auswahl,
welche Spalte ein- bzw. ausgeblendet
werden soll.
96
Abbildung 4.16: Dieselbe Tabelle,
nachdem Spalte 2 und 4 ausgeblendet
worden sind
KAPITEL 4. MOBILE SUPERX
4.5.5
97
Übersicht
Zur besseren Übersicht möchte ich abschließend Mobile SuperX in einem
Diagramm zusammenfassen. Abbildung 4.17 zeigt den vollständigen Ablauf
der Mobile SuperX-Nutzung und gibt an, auf welcher Seite der Arbeit die
einzelnen Komponenten erläutert werden. Durch die strikte Trennung der
Servlets des XML-Frontends und der von Mobile SuperX ist es möglich an
beiden Frontends parallel zu entwickeln, ohne dass sie sich gegenseitig negativ
beeinflussen können. Das Servlet MobileSuperxAbmeldung dient dazu, die
aktuelle Session zu beenden und wieder zur Anmeldung zurückzukehren. Der
komplette Quellcode von Mobile SuperX befindet sich auf der beigefügten
CD.
Abbildung 4.17: Der Ablauf von Mobile SuperX
KAPITEL 4. MOBILE SUPERX
4.6
98
Experimente: Browser und Pocket PC
In diesem Abschnitt möchte ich einige Versuche mit verschiedenen Technologien beschreiben. Die bisherigen Screenshots von Mobile SuperX stammen
alle vom Palm Tungsten C mit dem Palm Web Browser (Netfrond-Kern Version 3.0). Mobile SuperX wurde deshalb noch mit dem Pocket PC Dell Axim
X30 getestet. Er ist mit einem Intel PXA270 624MHz Prozessor ausgestattet
und verfügt über 64MB RAM. Die Auflösung beträgt 240*320, es ist also
im Gegensatz zum Tungsten C kein quadratisches Display. Ein großer Vorteil gegenüber allen Palms ist, dass der Dell Pocket PC mit Bluetooth und
WLAN ausgerüstet ist. Als Betriebssystem dient Windows Mobile 2003, die
Benutzerführung ist im Allgemeinen etwas weniger intuitiv im Vergleich zum
PalmOS. Standardmäßig ist der Internet Explorer Mobile installiert.
4.6.1
Internet Explorer Mobile
Mobile SuperX funktioniert auch auf dem Internet Explorer Mobile gut. Die
folgenden Screenshots sollen dies belegen:
Abbildung 4.18: Mobile SuperX auf
dem Pocket PC Internet Explorer
Abbildung 4.19: Das Menü im Internet
Explorer Mobile
KAPITEL 4. MOBILE SUPERX
99
Abbildung 4.20: Mobile SuperX Untermenü im PPC IE
Abbildung 4.21: Ein weiteres Untermenü im PPC IE
Abbildung 4.22: Mobile SuperX Maske
im PPC IE
Abbildung 4.23: Eine weitere Maske:
Studierende (gewichtet)
KAPITEL 4. MOBILE SUPERX
Abbildung 4.24: Eine kleine Tabelle im
Internet Explorer Mobile ...
4.6.2
100
Abbildung 4.25: ... und eine sehr große
Tabelle.
NetFront 3.1
Da für den Pocket PC eine Version von NetFront 3.1 zum Download angeboten wird, konnte der wahrscheinlich fortschrittlichste Browser ebenfalls
getestet werden. Großer Vorteil von NetFront sind die vielen verschiedenen
Einstellungen zur Darstellung der Webseite. Es gibt drei verschiedene Profile: Normal, JustFit, SmartFirt. Mit JustFit wird die Seite regelrecht auf
die Display-Breite gepresst, SmartFit ist nicht ganz so restriktiv. Des Weiteren hat man die Möglichkeit, zwischen fünf verschiedenen Zoom-Stufen und
ebenso zwischen fünf verschiedenen Schriftgrößen auszuwählen. So lassen sich
auch mittelgrosse Tabellen in Mobile SuperX ganz passabel darstellen, durch
Vollbildmodus und Querformat läß sich das Ergebnis weiter verbessern. Erfreulicherweise hat PalmSource im Oktober 2004 angekündigt, auch den Palm
Web Browser 3.0 mit dem NetFront-Kern auszustatten. Dies stärkt die Hoffnung, dass NetFront der de-facto-Standard für PDA-Browser wird und somit
die Entwicklung mobiler Browseranwendungen erleichtert. Hier folgen die
Screenshots der Tests:
KAPITEL 4. MOBILE SUPERX
101
Abbildung 4.26: Die Mobile SuperX
Anmeldung auf NetFront 3.1
Abbildung 4.27: Das Menü auf NetFront 3.1
Abbildung 4.28: Das Untermenü auf
NetFront 3.1
Abbildung 4.29: Die Maske “Studierende“
KAPITEL 4. MOBILE SUPERX
Abbildung 4.30: Die Tabelle “Absolventen“ auf NetFront 3.1
4.7
102
Abbildung 4.31: Die Tabelle “Studierende“ im Vollbildmodus
Zusammenfassung
Abschließend kann man sagen, dass mit Mobile SuperX ein durchaus einsetzbares Frontend für SuperX entstanden ist. Die Performance der aktuellen
PDAs reicht aus, um Anfragen aller Art an das Data Warehouse zu stellen.
Kleine und mittelgroße Tabellen lassen sich auf den PDA-Displays gut darstellen. Bei sehr großen Tabellen gibt es, wie zu erwarten war, Probleme, eine
erste Verbesserung steht in Zukunft durch die Ein-/Ausblenden-Funktion von
Spalten bereits bereit. Man sollte sich aber im Klaren darüber sein, das Mobile SuperX nicht dazu da ist, aufwendige Berichte zu erstellen, sondern dem
Nutzer schnellen und mobilen Zugriff auf prägnante Daten zu ermöglichen.
Die Datenübertragungsrate spielt bei den genutzten Standards eigentlich
keine große Rolle, da die zu übertragenden Seiten den einstelligen Kb-Bereich
nicht überschreiten. Wichtiger ist die Leistung des PDA-Prozessors, da er die
mit der Darstellung im Browser verbundenen Berechnungen durchführt. In
den Tests erwies sich so auch der Dell Pocket PC mit 624MHz als etwas
schneller als der Tungsten C mit 400MHz.
Obwohl voll funktionsfähig, ist die Entwicklung von Mobile SuperX an
dieser Stelle mit Sicherheit noch nicht abgeschlossen, vielmehr soll die erste Version als Basis für weitere Entwicklungen dienen. Mit neuen Browsern
KAPITEL 4. MOBILE SUPERX
103
und schnelleren PDAs werden neue Möglichkeiten entstehen, um die Bedienung und Benutzerfreundlichkeit weiter zu verbessern. Ebenso sind weitere
Funktionen denkbar, zum Beispiel könnten mit Hilfe der Lokalisierung des
verwendeten Access Points Informationen über den momentanen Standort
abgerufen werden (z.B. Inventarliste).
Die verwendete Technologie ist natürlich auch unabhängig von SuperX
anwendbar. Ein öffentlich zugängliches mobiles Informationssystem ist aufgrund der großen Verbreitung mobiler Endgeräte, insbesondere natürlich
Handys, mit Sicherheit auch ein spannendes Thema. Vorlesungsverzeichnis
und aktuelle Informationen aus der Universität könnten darin enthalten sein.
Mobile SuperX kann auch als Beispiel für die Entwicklung weiterer Frontends dienen, man kann hier zum Beispiel an einen barrierefreien Zugang zu
SuperX denken.
Kapitel 5
Diagramme für SuperX
Die Ergebnisse der Abfragen werden in SuperX momentan nur in Form von
Tabellen dargestellt. Oftmals kommt allerdings der Wunsch nach einer grafischen Darstellung des Inhalts durch Diagramme auf. Ein Ansatz zu einer
solchen Visualisierung der Daten sowie konkrete Beispiele werden in diesem
Kapitel beschrieben.
5.1
SVG: Scalable Vector Graphics
Es gibt unzählige verschiedene Grafikformate im Web. Für unsere Anforderungen eignet sich der W3C Vektorgrafikstandard Scalable Vector Graphics
(SVG)1 besonders gut. Im Gegensatz zu Pixelformaten, wie JPG, GIF oder
BMP, beschreibt SVG Bilder durch Objekte (Vektoren)[21]. Großer Vorteil
von SVG und Vektorgrafiken allgemein ist, dass Grafiken beliebig skaliert
werden können, ohne dass es zu einem Qualitätsverlust kommt.
Einführung in SVG
SVG ist eine auf XML basierende textorientierte Auszeichnungssprache, was
eine weitere sehr schöne Eigenschaft darstellt. Somit kann man SVG-Grafiken
mit jedem beliebigen Texteditor erstellen. Es gibt inzwischen auch schon
einige grafikbasierte Editoren, die den Standard unterstützen, so zum Beispiel
der Adobe Illustrator 10 und Corel Draw 12. SVG-Grafiken können entweder
in einem SVG-Viewer oder direkt im Browser angezeigt werden. Adobes SVG
Viewer 3.0 2 ist als Browser-Plugin für die Plattformen Windows und Mac
frei erhältlich. Das Apache XML Project stellt mit Batik 1.5 Squiggle einen
1
2
http://www.w3.org/TR/SVG11/
http://www.adobe.com/svg/viewer/install/main.html
104
KAPITEL 5. DIAGRAMME FÜR SUPERX
105
java-basierten, eigenständigen Viewer zur Verfügung[23], Batik beinhaltet
weitere SVG-Tools, auf die ich später teilweise noch eingehen werde. Sehr
viel versprechend ist auch der Ansatz von Access, mit ihrem NetFront SVG
Viewer mobile Geräte mit der neuen Technologie kompatibel zu machen.
Das W3C hat dafür zwei weitere Empfehlungen verabschiedet: SVG Tiny für
Handys und SVG Basic für PDAs3 .
Als etwas gewöhnungsbedürftig stellt sich das Koordinatensystem in SVG
heraus, der Ursprung liegt in der linken oberen Ecke. Die X-Achse verläuft
also wie üblich nach rechts, die Y-Achse aber nach unten. Die einfachste
Struktur in SVG stellen Linien dar, eine Linie zwischen den Punkten (1/2)
und (4/3) wird folgendermaßen beschrieben:
< line x1 ="1" y1 ="2" x2 ="4" y2 ="3" / >
Ein Rechteck lässt sich ähnlich einfach erzeugen:
< rect x ="1" y ="1" width ="50" height ="20" / >
Der Punkt (x/y) beschreibt dabei die Lage der linken oberen Ecke des Rechteckes. Um eine Kreis zu zeichnen gibt man den Mittelpunkt sowie den Radius
an:
< circle cx ="20" cy ="20" r ="12" / >
Mit Ellipse, Polygon und Pfad sind weitere Formen definiert, auf die ich
hier aber nicht eingehen möchte, da sie für unsere SuperX-Diagramme nicht
benötigt werden. In dem Beispiel im nächsten Abschnitt wird die SVGSyntax ausführlicher beschrieben. Neben der Erzeugung geometrischer Objekte kann auf diese auch interaktiv zugegriffen und es können Hyperlinks
auf ihnen definiert werden. Des Weiteren können mit SVG Animationen innerhalb der Grafik erstellt werden.
5.2
SuperX-Diagramme mit SVG
Wie Diagramme für SuperX gestaltet werden können, wird in diesem Abschnitt beispielhaft erläutert. Als Datenquelle dienten hier StudierendenStatistiken aus der Universität Freiburg, da sich die Daten aus dem bis jetzt
einzigen Modul (COB) zur Veranschaulichung eines Ansatzes nur schlecht
eigneten. Dafür wurde mit PhpPgAdmin zunächst eine einfache Tabelle zu
der SuperX PostgreSQL-Datenbank hinzugefügt: Sie heißt stat absolventen
und beinhaltet die Anzahl der Absolventen im Studiengang Diplom Informa3
http://www.w3.org/TR/SVGMobile/
KAPITEL 5. DIAGRAMME FÜR SUPERX
106
tik seit 1998:
Jahr Anzahl
98
4
99
7
00
21
01
11
02
14
03
27
Zur Visualisierung dieser Tabelle eignet sich ein Balkendiagramm sehr gut.
5.2.1
Eine statische SVG-Grafik
Zu Beginn werde ich ein Balkendiagramm für die Absolventen-Statistik durch
ein SVG-Dokument erzeugen, wobei die Daten der Tabelle im Dokument
angegeben werden. Wie bei jedem XML-Dokument beginnt auch eine SVGDatei mit der XML-Deklaration. In der Dokument-Typ-Deklaration folgen
der Public und der Document Identifier, daraus kann eine Anwendung (Parser) ableiten, welche Regeln für das XML-Dokument gelten.
Listing 5.1: absolventen balken.svg
<? xml version ="1.0"? >
<! DOCTYPE svg PUBLIC " -// W3C // DTD SVG 1.0// EN " " http ://
• www . w3 . org / TR /2001/ REC - SVG -20010904/ DTD / svg10 . dtd " >
Als nächstes folgt das Wurzelelement mit der Definition der viewBox, deren
Rand schwarz ist:
< svg viewBox ="0 130 300 200" stroke =" black " >
Danach wird ein Rechteck erzeugt, um den Hintergrund der Grafik weiß zu
färben:
< rect x ="0" y ="0" width ="300" height ="200" fill =" white
• " stroke =" white " / >
Mit <g> und </g> wird eine Gruppe gebildet, deren Mitglieder alle die gleichen Eigenschaften besitzen, hier wird die Randstärke auf zwei gesetzt. Danach folgt, wiederum mit Hilfe eines Rechtecks, die Erzeugung des Rahmens
für unser Diagramm. Die einzelnen Balken werden ebenfalls durch Rechtecke
gebildet und unterschiedlich eingefärbt. Fünf Pixel entsprechen dabei einem
Absolventen.
KAPITEL 5. DIAGRAMME FÜR SUPERX
107
<g fill =" none " stroke - width ="2" >
<! - - Rahmen -->
< rect x ="30"
y ="140" width ="250" height ="160" / >
<! - - Die Balken der Grafik -->
< rect x ="55"
y ="280" width ="25" height ="20" fill
• =" skyblue " / >
< rect x ="90"
y ="265" width ="25" height ="35" fill
• =" cornflowerblue " / >
< rect x ="125" y ="195" width ="25" height ="105"
• fill =" skyblue " / >
< rect x ="160" y ="245" width ="25" height ="55"
• fill =" cornflowerblue " / >
< rect x ="195" y ="230" width ="25" height ="70"
• fill =" skyblue " / >
< rect x ="230" y ="165" width ="25" height ="135"
• fill =" cornflowerblue " / >
</g >
Die Balken sind jetzt erzeugt. Zur besseren Übersicht werden jetzt gestrichelte Linien eingefügt, jeweils nach fünf Einheiten (Absolventen) der Y-Achse,
also alle 25 Pixel.
<g fill =" none " stroke - width ="0.5"
• ="5" >
< line x1 ="20" y1 ="250" x2 ="280"
< line x1 ="20" y1 ="200" x2 ="280"
< line x1 ="20" y1 ="150" x2 ="280"
< line x1 ="20" y1 ="175" x2 ="280"
< line x1 ="20" y1 ="225" x2 ="280"
< line x1 ="20" y1 ="275" x2 ="280"
</g >
stroke - dasharray
y2 ="250"
y2 ="200"
y2 ="150"
y2 ="175"
y2 ="225"
y2 ="275"
/>
/>
/>
/>
/>
/>
Danach beschriftet man die Y-Achse an den gestrichelten Linien mit Hilfe
des Elementes <text>:
<g fill =" black " stroke =" none " font - size ="12" >
<g text - anchor =" end " >
< text x ="20" y ="279" >5 </ text >
< text x ="20" y ="254" >10 </ text >
< text x ="20" y ="229" >15 </ text >
< text x ="20" y ="204" >20 </ text >
< text x ="20" y ="179" >25 </ text >
< text x ="20" y ="154" >30 </ text >
</g >
KAPITEL 5. DIAGRAMME FÜR SUPERX
108
Abbildung 5.1: absolventen balken.svg in Viewer Squiggle
</g >
Auch die X-Achse wird mit <text> beschriftet und anschließend das SVGElement beendet:
<g fill =" black " stroke =" none " font - size ="12" >
<g text - anchor =" middle " >
< text x ="67.5" y ="315" >98 </ text >
< text x ="102.5" y ="315" >99 </ text >
< text x ="137.5" y ="315" >00 </ text >
< text x ="172.5" y ="315" >01 </ text >
< text x ="207.5" y ="315" >02 </ text >
< text x ="242.5" y ="315" >03 </ text >
</g >
</g >
</ svg >
Das Ergebnis des SVG-Dokuments im Squiggle-Viewer ist in Abbildung 5.1
zu sehen.
5.2.2
Eine dynamische SVG-Grafik
Das oben gezeigte SVG-Dokument wurde statisch erzeugt, wir möchten aber
aus den Ergebnissen der SuperX-Abfragen dynamisch Diagramme erstellen.
Zu Testzwecken schreibt man dafür ein XML-Dokument mit der AbsolventenTabelle als Inhalt, wie es auch SuperX als Ergebnis einer Abfrage hätte liefern
können. Man hält sich dabei an die in Kapitel 4.5.4 angegebene DTD:
KAPITEL 5. DIAGRAMME FÜR SUPERX
109
Listing 5.2: tabelle.xml
<? xml version ="1.0" encoding =" UTF -8"? >
<! DOCTYPE sqlerg SYSTEM " C :\ Diplomarbeit \ doku \ code \ SVG \
• tabelle . dtd " >
< sqlerg >
< headers >
< header >
< wert > Jahr </ wert >
</ header >
< header >
< wert > Anzahl </ wert >
</ header >
</ headers >
<row >
<col > < id / > < f_name / >
< wert >98 </ wert >
</ col >
<col > < id / > < f_name / >
< wert >4 </ wert >
</ col >
</ row >
<row >
<col > < id / > < f_name / >
< wert >99 </ wert >
</ col >
<col > < id / > < f_name / >
< wert >7 </ wert >
</ col >
</ row >
<row >
<col > < id / > < f_name / >
< wert >00 </ wert >
</ col >
<col > < id / > < f_name / >
< wert >21 </ wert >
</ col >
</ row >
<row >
<col > < id / > < f_name / >
< wert >01 </ wert >
</ col >
<col > < id / > < f_name / >
< wert >11 </ wert >
KAPITEL 5. DIAGRAMME FÜR SUPERX
110
</ col >
</ row >
<row >
<col > < id / > < f_name / >
< wert >02 </ wert >
</ col >
<col > < id / > < f_name / >
< wert >14 </ wert >
</ col >
</ row >
<row >
<col > < id / > < f_name / >
< wert >03 </ wert >
</ col >
<col > < id / > < f_name / >
< wert >27 </ wert >
</ col >
</ row >
</ sqlerg >
Wir können das XML-Dokument nun wiederum mit einem XSL-Stylesheet
transformieren. Allerdings wird diesmal nach SVG und nicht nach HTML
transformiert, möglich ist das, weil man auch nach XML transformieren kann
und SVG ist eben gerade XML. Man beginnt das Stylesheet wie üblich mit
der ersten Template:
Listing 5.3: svg abs.svg
<? xml version ="1.0" encoding =" UTF -8"? >
< xsl : stylesheet version ="1.0" xmlns : xsl =" http :// www . w3 .
• org /1999/ XSL / Transform " >
< xsl : template match ="/" >
Nun wird analog zum statischen Beispiel der SVG-Teil mit der Viewbox
begonnen:
< svg viewBox ="0 130 300 200" stroke =" black " >
< rect x ="0" y ="0" width ="300" height ="200" fill ="
• white " stroke =" white " / >
Die beiden Templates balken und x-achse werden aufgerufen:
< xsl : call - template name =" balken "/ >
< xsl : call - template name =" x - achse "/ >
KAPITEL 5. DIAGRAMME FÜR SUPERX
111
An dieser Stelle sind die Balken und die Beschriftungen der X-Achse durch
die Templates bereits erstellt. Die gestrichelten Linien sowie deren Beschriftungen werden darüber gezeichnet:
<g fill =" none " stroke - width ="0.5" stroke - dasharray
• ="5" >
< line x1 ="20" y1 ="250" x2 ="280" y2 ="250" / >
< line x1 ="20" y1 ="200" x2 ="280" y2 ="200" / >
< line x1 ="20" y1 ="150" x2 ="280" y2 ="150" / >
< line x1 ="20" y1 ="175" x2 ="280" y2 ="175" / >
< line x1 ="20" y1 ="225" x2 ="280" y2 ="225" / >
< line x1 ="20" y1 ="275" x2 ="280" y2 ="275" / >
</g >
<g fill =" black " stroke =" none " font - size ="12" >
<g text - anchor =" end " >
< text x ="20" y ="279" >5 </ text >
< text x ="20" y ="254" >10 </ text >
< text x ="20" y ="229" >15 </ text >
< text x ="20" y ="204" >20 </ text >
< text x ="20" y ="179" >25 </ text >
< text x ="20" y ="154" >30 </ text >
</g >
</g >
</ svg >
</ xsl : template >
Die Template balken definiert zuerst wieder den Rahmen, dann wird für jede
Reihe des Ergebnisses die Template balken2 aufgerufen:
< xsl : template name =" balken " >
<g fill =" none " stroke - width ="2" >
<! - - Rahmen -->
< rect x ="30"
y ="140" width ="250" height ="160" / >
<! - - Die Balken der Grafik -->
< xsl : for - each select =" sqlerg / row " >
< xsl : call - template name =" balken2 " / >
</ xsl : for - each >
</g >
</ xsl : template >
Zu Beginn der Template balken2 werden die Variablen p und pos definiert.
Danach wird jede Spalte (einer Zeile) einmal in die Hand genommen. Ist die
aktuelle Position der Schleife größer als “1“, dann werden die Rechtecke für
die Balken gezeichnet. Die erste Spalte (Jahreszahl) der Ergebnistabelle wird
KAPITEL 5. DIAGRAMME FÜR SUPERX
112
damit zunächst außen vor gelassen, wir brauchen sie später zur Beschriftung der X-Achse. Die Höhe der Balken wird anhand von <wert> berechnet
und die Koordinaten mit Hilfe der position()-Funktion. Mit <xsl:choose>
wird eine if-then-else-Schleife gebildet, um wie oben die Balken abwechselnd
einzufärben:
< xsl : template name =" balken2 " >
< xsl : variable name =" p " select =" position () "/ >
< xsl : variable name =" pos " select ="(( position () -1) *35)
• +55"/ >
< xsl : for - each select =" col " >
< xsl : if test =" position () & gt ; 1" >
< xsl : choose >
< xsl : when test =" $p mod 2" >
< rect x ="{ $pos }" y ="{300 -( wert *5) }"
• width ="25" height ="{ wert *5}" fill ="
• skyblue " / >
</ xsl : when >
< xsl : otherwise >
< rect x ="{ $pos }" y ="{300 -( wert *5) }"
• width ="25" height ="{ wert *5}" fill ="
• cornflowerblue " / >
</ xsl : otherwise >
</ xsl : choose >
</ xsl : if >
</ xsl : for - each >
</ xsl : template >
Mit der ersten Spalte wird die X-Achse beschriftet. Der Text wird mittig zu
den Koordinaten ausgerichtet:
< xsl : template name =" x - achse " >
<g fill =" black " stroke =" none " font - size ="12" >
<g text - anchor =" middle " >
< xsl : for - each select =" sqlerg / row " >
< xsl : call - template name =" x - achse2 " / >
</ xsl : for - each >
</g >
</g >
</ xsl : template >
Nur die Werte der ersten Spalten jeder Reihe werden ausgewählt und als
Text in die Grafik eingefügt:
KAPITEL 5. DIAGRAMME FÜR SUPERX
113
< xsl : template name =" x - achse2 " >
< xsl : variable name =" posx " select ="(( position () -1)
• *35) +67.5"/ >
< xsl : for - each select =" col " >
< xsl : if test =" position () & lt ; 2" >
< text x ="{ $posx }" y ="315" > < xsl : value - of
• select =" wert " / > </ text >
</ xsl : if >
</ xsl : for - each >
</ xsl : template >
</ xsl : stylesheet >
Um die Transformation durchführen zu können, benötigt man einen XSLTProzessor. Ich verwende an dieser Stelle das Paket Xalan4 der Apache Group.
Mit dem folgenden Aufruf (Windows) wird tabelle.xml durch svg abs.xsl
in absxslt.svg transformiert:
C:\> java -cp c:\xalan-j_2_5_2\bin\xalan.jar org.apache.xalan.xslt.Process
-in tabelle.xml -xsl svg_abs.xsl -out absxslt.svg
Damit wird exakt dieselbe SVG-Grafik erstellt, wie schon in Abbildung 5.1
zu sehen! Man könnte jetzt noch fortfahren und die Grafik auf weitere Balken
vorbereiten: Sobald die Anzahl der Reihen in der Ergebnistabelle größer als
sechs ist, wird die Breite der Balken proportional verkleinert und ebenfalls
die X-Koordinate entsprechend nach links verschoben. Die Beschriftung der
X-Achse wurde um dieselbe Anzahl Pixel verschoben. Hier sollte aber wie
gesagt nur ein Ansatz vorgestellt werden.
5.2.3
SVG auf dem Webserver
Da SVG ein Standard für das Internet ist, sollen die SVG-Dateien auch auf
einem Webserver abgelegt werden. Dies gilt natürlich auch für die SVGGrafiken, die mit SuperX genutzt werden sollen. Man muss dabei zwei Fälle
unterscheiden:
1. Client mit Browser-Plugin
2. Client ohne Browser-Plugin
4
http://xml.apache.org/xalan-j/
KAPITEL 5. DIAGRAMME FÜR SUPERX
114
Client mit Browser-Plugin
Werden die SVG-Dateien (z.B. absolventen balken.svg) fertig auf dem Webserver abgelegt, dann sendet er diese auch problemlos an die Clients. Man sollte
allerdings die Beziehung zwischen Medientyp und Dateiendung in der Zuordnungstabelle angeben. Dies ist häufig noch nicht der Fall. Beim Apachen
zum Beispiel ergänzt man die Zuordnungsdatei mime.types um den Eintrag:
image / svg + xml
svg svgz
Innerhalb von HTML-Dokumenten kann man SVG-Dateien durch object
oder embed einbetten:
< embed src =" abolventen . svg " type =" image / svg + xml " witdh
• ="300" height ="200" / >
Sollen die SVG-Dateien allerdings dynamisch erzeugt werden, so wie dies in
Kapitel 5.2.2 geschehen ist, muss der Medientyp im Servlet innerhalb der
Methode doPost(), beziehungsweise doGet(), angegeben werden.
Client ohne Browser-Plugin
Schwieriger gestaltet sich das Ganze, wenn der Browser über kein SVGPlugin verfügt. In diesem Fall muss die SVG-Grafik rasterisiert und in einem Pixelformat gespeichert werden. Batik enthält dafür die Jar-Datei batikrasterizer.jar. Der folgende Befehl (Windows) erzeugt die Rastergrafik
absolventen balken.jpg aus absolventen balken.svg:
C:\> java -jar batik-rasterizer.jar -m image/jpeg -w 300 -h 200
absolventen_balken.svg
Dieser Vorgang kann auch automatisiert werden, Bader zeigt in [21] einen
Weg. So wird dann nur nach Bedarf das Rasterbild überhaupt erstellt, ist ein
Plugin vorhanden, wird direkt die SVG-Grafik angezeigt.
5.2.4
Einbindung in SuperX
Ich gehe an dieser Stelle nur auf die Einbindung von SVG-Diagrammen
in XML-basierte Frontends (XML, Mobile SuperX) ein. Im Fall von SuperX wäre denkbar ein weiteres Servlet zu erstellen, welches nach Bedarf
ein ähnliches XML-Dokument erzeugt wie MobileSuperxTabelle. Das XSLStylesheet, zum Beispiel svg abs.xsl, wird wieder als Stil im Servlet angegeben. Nach dem die Tabelle angezeigt wird, kann ein Hyperlink auf das
neue Servlet verweisen. Durch Markierung mit Hilfe von Checkboxen könnten
KAPITEL 5. DIAGRAMME FÜR SUPERX
Abbildung 5.2: SVG-Diagramm der
Absolventen in Mobile SuperX
115
Abbildung 5.3: SVG-Diagramm der
Anzahl Studierende in Mobile SuperX
die Spalten ausgewählt werden, welche als Balken im Diagramm erscheinen
sollen.
Anstatt der Tabelle könnte das SVG-Diagramm auch direkt angezeigt
werden. Eine Auswahl des gewünschten Anzeigeformates würde dann schon
in der Maske vorgenommen.
Um variabler zu sein, kann das Stylesheet in Kapitel 5.2.2 natürlich noch
weiter für verschiedene Abfragen verbessert werden. Grundsätzlich scheint es
jedoch sinnvoll, mehrere Stylesheets zu erstellen und diese für einzelne Abfragen zu optimieren. Weitere Diagrammarten sind auch denkbar, zum Beispiel
ein Kuchendiagramm für die Geburtslandstatistik ausländischer Studierender.
Zum Abschluss dieses Kapitels möchte ich noch die Screenshots präsentieren, die bei der Integration der Diagramme in Mobile SuperX entstanden sind. Dafür wurden mit Hilfe des SuperX-Admin-Tools neue Abfragen
in die Tabelle themenbaum eingefügt, eine Anleitung dazu ist im Administratorhandbuch zu finden (Anmerkung: die Abfragen sind bereits auf den
Screenshots in Kapitel 4 zu sehen). Abbildung 5.2 zeigt, dass das rasterisierte
absolventen balken.svg auch auf PDAs sehr gut dargestellt werden kann.
In Abbildung 5.3 ist ein Diagramm zu sehen, welches die Gesamtanzahl der
Studierenden angibt (Quellcode befindet sich auf der beigefügten CD), dabei
wurde auch das Geschlecht der Studierenden visualisiert. Die Abbildung 5.4
zeigt die gleiche Seite wie Abbildung 5.2, allerdings wurde hier Mobile SuperX im Internet Explorer mit installiertem Adobe SVG Viewer aufgerufen,
die SVG-Grafik wird also nicht rasterisiert. Hier ist dann auch das Zoomen
KAPITEL 5. DIAGRAMME FÜR SUPERX
116
Abbildung 5.4: SVG-Diagramm der Absolventen im Internet Explorer
möglich.
Kapitel 6
Abschlussbetrachtung und
Ausblick
Das Data Warehouse SuperX wird in Zukunft mit Sicherheit einen wichtigen
Platz an der Universität einnehmen. Die Bestrebungen, SuperX landesweit
als Hochschulinformationssystem einzusetzen, unterstützen dies. Ab Anfang
2005 soll das SOS-Modul in Freiburg in einer Pilotphase getestet werden, womit ein weiterer wichtiger Schritt gemacht wäre. Schön ist auch die Möglichkeit, leicht eigene Datenquellen in SuperX zu integrieren, so wie dies mit den
Statistikabfragen in Kapitel 5 geschah.
Mit der Entwicklung von Mobile SuperX wird das System um eine weitere
Komponente erweitert, für die durchaus Nachfrage und Anwendung besteht.
Dabei bleibt abzuwarten, wie sich der PDA-Markt in Zukunft entwickelt und
wie sich dieser gegen die stark aufkommende Smartphonebranche behaupten
kann. Hoffnung auf weitere Erfolg versprechende Entwicklungen macht auf
alle Fälle Access und deren PDA-Browser NetFront. Mit XML und XSL setzt
SuperX auf zwei besonders zukunftssichere und ausbaufähige Technologien.
Mit den SVG-Diagrammen wurde ein Ansatz gezeigt, wie variabel einsetzbar
diese im Einsatz tatsächlich sind. Eine umfassende Realisierung von SVGDiagrammen würde sicherlich problemlos eine ganze Arbeit ausfüllen.
Das Potential von XSL ist damit bei weitem noch nicht ausgeschöpft,
mit XSL-FO beispielsweise lassen sich aus den Abfragen PDF-Dokumente
designen. Auch in der Verbindung von SVG und Mobile SuperX sind für die
Zukunft interessante Projekte denkbar. So zum Beispiel ein interaktiver Plan
der Universität, welcher dem Benutzer mit Hilfe der Access Points Standort
und Routen aufzeigen könnte. Die dreidimensionale Umsetzung eines OLAPWürfels ist auf Basis von SVG mit Hilfe von Animationen ebenfalls machbar.
Es würde mich sehr freuen, wenn die vorliegende Arbeit für weitere als
Anregung dienen könnte.
117
Literaturverzeichnis
[1] Meditsch, U. (2001). SuperX-Präsentation in Duisburg. Duisburg
[2] Bauer, A. & Günzel, H. (2004). Data Warehouse Systeme (2. Auflage).
Heidelberg: dpunkt.verlag.
[3] Muksch, H. & Behme, W. (2000). Das Data Warhouse-Konzept (4. Auflage). Wiesbaden: Gabler
[4] Greenfield, L. (2004) The Data Warehousing Information Center.
http://www.dwinfocenter.org.
[5] Quathamer, D., Bisping, M. & Winterstein, M. (2003). SuperXBenutzerhandbuch. Wuppertal: Memtext
[6] Quathamer, D. & Bisping, M. (2004). SuperX-Administratorhandbuch
Kernmodul. Wuppertal: Memtext
[7] Nusselin, M. (2003). Inhaltliche Gestaltung eines Data WarehouseSystems am Beispiel einer Hochschule München: IHF.
[8] Kofler, M. (2004). Linux: Installation, Konfiguration, Anwendung (7.
Auflage). München: Addison-Wesley.
[9] Eisentraut, P. (2003). PostgreSQL (1. Auflage) Bonn: Mitp.
[10] heise online. (17.11.2004). PostgreSQL in Version 7.4 veröffentlicht.
http://www.heise.de/newsticker/result.xhtml?url=/newsticker/meldung/
42093&words=Data%20Warehouse
[11] Tanenbaum, A. (2003). Computer Networks (Fourth Edition). New Jersey: Pearson Education.
[12] Access, Inc. (25.09.2003). ACCESS NetFront Browser Technology Powers High-End Palm Tungsten C. http://www.access-syseu.com/index.php?id=97&type=98)
118
LITERATURVERZEICHNIS
119
[13] Zucker, D., Uematsu, M. & Kamada, T. (2003) Ubiquitos Web Browsing:
Evolving Toward Universal Access Everywhere, Tokio: Access
[14] Roth, J. (2002).
dpunkt.verlag.
Mobile
Computing
(1.
Auflage)
Heidelberg:
[15] PostgreSQL.org. (15.12.2004). How does PostgreSQL compare to other
DBMSs. http://www.postgresql.org/docs/faqs/FAQ.html#1.14.
[16] Hunter, J. & Crawford, W. (2001). Java Servlet Programming (Second
Edition). Sebastopol: O’Reilly.
[17] Ray, E. (2004). Einführung in XML (2. Auflage). Köln: O’Reilly.
[18] Burke, E. (2002). Java und XSLT (1. Auflage) Köln: O’Reilly.
[19] Tidwell, D. (2002). XSLT (1. Auflage). Köln: O’Reilly.
[20] Zytrax, Inc. (20.10.2004). Mobile Browser ID (User-Agent) Strings.
http://www.zytrax.com/tech/web/mobile ids.html
[21] Bader, H. (2004). SVG Reporting: Vektorgrafiken im Web einsetzen (1.
Auflage). Frankfurt: Software und Support Verlag.
[22] Pohlmann, R. (2004). SVG Tutorial. http://svg.tutorial.aptico.de
[23] The Apache Software Foundation. (2004). Batik SVG Toolkit.
http://xml.apache.org/batik/
Herunterladen